博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
数据结构排序算法学习之插入排序(总)
阅读量:3939 次
发布时间:2019-05-24

本文共 3717 字,大约阅读时间需要 12 分钟。

数据结构排序算法之插入排序<一>

插入排序(Insertion sort)

是一种简单直观且稳定的排序算法。如果有一个已经有序的数据序列,要求在这个已经排好的数据序列中插入一个数,但要求插入后此数据序列仍然有序,这个时候就要用到一种新的排序方法——插入排序法,插入排序的基本操作就是将一个数据插入到已经排好序的有序数据中,从而得到一个新的、个数加一的有序数据,算法适用于少量数据的排序,时间复杂度为O(n^2)。是稳定的排序方法。插入算法把要排序的数组分成两部分:第一部分包含了这个数组的所有元素,但将最后一个元素除外(让数组多一个空间才有插入的位置),而第二部分就只包含这一个元素(即待插入元素)。在第一部分排序完成后,再将这个最后元素插入到已排好序的第一部分中。

插入排序的基本思想

每步将一个待排序的记录,按其关键码值的大小插入前面已经排序的文件中适当位置上,直到全部插入完为止。

分类

emmmm这里只说三种主要的:

  1. 直接插入排序
  2. 折半插入排序(二分插入排序)
  3. 希尔排序(又称缩小增量排序)

1.直接插入排序

把n个待排元素分为有序区和无序区,开始时有序区中只包含1个元素,无序区中则包含n-1个元素,排序过程中每次都从无序区中取出第一个元素,将它插入到有序区中的适当位置,使之成为一个有序的表,重复n-1次可完成排序过程。

Java实现:

package priv.qcy.sort.insert;public class InsertSort {	public static void insertSort(int[] a, int n) {		int i, j;		for (i = 1; i < n; i++) {			int temp = a[i];			for (j = i - 1; j >= 0 && a[j] > temp; j--) {				a[j + 1] = a[j];			}			a[j + 1] = temp;		}	}	public static void main(String[] args) {		int[] a = { 20, 40, 30, 10, 60, 50 };		System.out.print("排序前:");		for (int i = 0; i < a.length; i++) {			System.out.print(a[i] + "  ");		}		System.out.println();		insertSort(a, a.length);		System.out.print("排序后:");		for (int i = 0; i < a.length; i++) {			System.out.print(a[i] + "  ");		}	}}

直接插入排序时间复杂度

直接插入排序的时间复杂度是O(N^2)。
假设被排序的数列中有N个数。遍历一趟的时间复杂度是O(N),而直接插入排序需要遍历N-1次。因此,直接插入排序的时间复杂度是O(N^2)。

直接插入排序稳定性

直接插入排序是稳定的算法,它满足稳定算法的定义。
算法稳定性 – 假设在数列中存在a[i]=a[j],若在排序之前,a[i]在a[j]前面;并且排序之后,a[i]仍然在a[j]前面。则这个排序算法是稳定的!

特点

  1. 也适用于链式存储结构
  2. 更适用于初始记录基本有序的情况(当N较大且无序时,此算法时间复杂度较高)

2.折半插入排序

基本思想:

折半插入算法是对直接插入排序算法的改进,排序原理同。

例子:int[] arr={5,2,6,0,9};经行折半插入排序

在这里插入图片描述

Java实现:

package priv.qcy.sort.insert;public class BinaryInsertSort {	public static void binaryInsertSort(int[] a) {		int n = a.length;		int i, j;		for (i = 1; i < n; i++) {			int temp = a[i];			int low = 0;			int high = i - 1;			while (low <= high) {				int mid = (low + high) / 2;				if (a[mid] > temp) {					high = mid - 1;				} else {					low = mid + 1;				}			}			for (j = i - 1; j >= low; j--) {				a[j + 1] = a[j];			}			a[low] = temp;		}	}	public static void main(String[] args) {		int[] a = { 20, 40, 30, 10, 60, 50 };		System.out.print("排序前:");		for (int i = 0; i < a.length; i++) {			System.out.print(a[i] + "  ");		}		System.out.println();		binaryInsertSort(a);		System.out.print("排序后:");		for (int i = 0; i < a.length; i++) {			System.out.print(a[i] + "  ");		}	}}

时间复杂度:可以看出,折半插入排序减少了比较元素的次数,约为O(nlogn),比较的次数取决于表的元素个数n。因此,折半插入排序的时间复杂度仍然为O(n²),但它的效果还是比直接插入排序要好。

空间复杂度:排序只需要一个位置来暂存元素,因此空间复杂度为O(1)。

特点:

  • 只适用于顺序结构
  • 适合初始记录无序,n较大的情况
  • 稳定,相对于直接插入排序元素减少了比较次数

3.希尔排序(递减增量排序)

希尔排序从“减少记录个数”和“序列基本有序”两个方面对直接插入排序算法进行改进,但插入排序一般来说是低效的,因为插入排序每次只能将数据移动一位。

基本思想:

先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序。

对于n个待排序的数列,取一个小于n的整数gap(gap被称为步长)将待排序元素分成若干个组子序列,所有距离为gap的倍数的记录放在同一个组中;然后,对各组内的元素进行直接插入排序。 这一趟排序完成之后,每一个组的元素都是有序的。然后减小gap的值,并重复执行上述的分组和排序。重复这样的操作,当gap=1时,整个数列就是有序的。

希尔排序

Java实现:

package priv.qcy.sort.insert;public class ShellSort {	public static void shellSort(int[] a, int n) {		for (int gap = n / 2; gap > 0; gap /= 2) {			for (int i = 0; i < gap; i++) {				for (int j = i + gap; j < n; j += gap) {					if (a[j] < a[j - gap]) {						int temp = a[j];						int k = j - gap;						while (k >= 0 && a[k] > temp) {							a[k + gap] = a[k];							k -= gap;						}						a[k + gap] = temp;					}				}			}		}	}	public static void main(String[] args) {		int[] a = { 9, 1, 2, 5, 7, 4, 8, 6, 3, 5 };		System.out.print("排序前:");		for (int i = 0; i < a.length; i++) {			System.out.print(a[i] + "  ");		}		System.out.println();		shellSort(a, a.length);		System.out.print("排序后:");		for (int i = 0; i < a.length; i++) {			System.out.print(a[i] + "  ");		}	}}

特点:

  • 是插入排序的一种更高效的改进版本,但跳跃导致希尔排序是非稳定排序算法。
  • 只适用于顺序结构
  • 适用于初始记录无序,n较大时的情况

希尔排序时间复杂度

希尔排序的时间复杂度与增量(即,步长gap)的选取有关。例如,当增量为1时,希尔排序退化成了直接插入排序,此时的时间复杂度为O(N²),而Hibbard增量的希尔排序的时间复杂度为O(N3/2)。

还有几种待补充

转载地址:http://cinwi.baihongyu.com/

你可能感兴趣的文章
fail2ban的使用-控制连接数
查看>>
btkill-连接数控制
查看>>
dhcp.conf
查看>>
关于win10的升级
查看>>
cacti突然不显示流量
查看>>
发现一个好工具记录一下,U盘启动ISO文件。
查看>>
centos7下配置网卡以及查询网卡UUID
查看>>
适用于旧计算机的10款最佳轻量级Linux发行版
查看>>
在VMware Workstation中批量创建上千台虚拟机
查看>>
linux常用软件收集
查看>>
linux查看桌面环境
查看>>
centos8安装ntfs-3g后,不能自动挂载U盘(NTFS格式)
查看>>
Linux安装显卡驱动
查看>>
使用minicom
查看>>
linux常用外设-打印机指纹和蓝牙的安装管理
查看>>
记录一下安装在移动硬盘上的fedora linux v33在各种笔记本下的兼容性
查看>>
关于安装系统后不能启动的问题!
查看>>
U盘的挂载过程-先记录一下
查看>>
python程序启动过程报错的排错一般步骤
查看>>
linux下UEFI的管理
查看>>