数据结构之插入排序
参考----王道论坛2015年数据结构联考复习指南----
算法稳定性:如果待排序表中有任意两个元素x1,x2相等,且排序前x1在x2的前面,使用某个排序算法之后,若x1仍然在x2的前面,则这个排序算法是稳定的.
一. 插入排序
- 直接插入排序:最直观最简单的排序,适用于顺序存储和链式存储的线性表.
- 折半插入排序:用了折半查找的排序,减少了元素的比较次数.
- 希尔排序:又称为缩小增量排序.
-
直接插入排序
实现将元素L(i)插入到已经有序的子序列L[1...i-1],中,需要执行:
(1)查找L(i)在L[1...i-1]中的插入位置k.
(2)将L[k...i-1]中的所有元素后移一位.
(3)将L(i)复制到L(k).
时间复杂度:O(n2),空间复杂度:O(1),稳定,算法代码如下:
1 void InsertSort(ElemType A[], int n) 2 { 3 int i,j; 4 for (i=2;i<=n;i++) 5 { 6 if (A[i]<A[i-1]) 7 { 8 A[0]=A[i]; 9 for (j=i-1;A[0]<A[j];--j) 10 A[j+1]=A[j]; 11 A[j+1]=A[0] 12 } 13 } 14 }
2. 折半插入
与直接插入类似,不同的是先找到(折半查找)要插入的位置,在移动插入点之后的所有元素.
时间复杂度为O(n2),空间复杂度O(1),稳定,算法代码如下:
1 void InsertSort(ElemType A[],int n) 2 { 3 int i,j,low,high,mid; 4 for (i=2;i<=n;i++) 5 { 6 A[0]=A[i]; 7 low=1;high=i-1; 8 while(low<=high) //查找位置 9 { 10 mid=(low+high)/2; 11 if (A[mid]>A[0]) 12 high=mid-1; 13 else 14 low=mid+1; 15 } 16 for (j=i-1;j>=high+1;--j) 17 { 18 A[j+1]=A[j]; //移动元素 19 } 20 A[high+1]=A[0]; 21 } 22 }
3. 希尔排序
直接插入排序适用于基本有序的排序表和数据量不大的排序表,基于此,出现了希尔排序,又称缩小增量排序.
基本思想:先将待排序表分割成若干形如L[i,i+d,i+2d...i+kd]的特殊子表,分别进行直接插入排序,直到整个表已经是基本有序,再对全体进行一次直接插入排序.
流程如下:先取一个小于n的步长d1,把表中的全部记录分成d1个组,所有距离为d1的倍数的记录放在同一个组中,在各组中进行直接插入排序;然后取第二个步长d2<d1,重复上述过程,直到dt=1,即所有记录放在同一组中,再进行直接插入排序,希尔提出的增量序列为d1=n/2;di+1=floor(di/2),(floor:向下取整函数),并且最后一个增量为1.
时间复杂度:最坏情况下为O(n2),空间复杂度为O(1),不稳定,算法代码如下:
1 void ShellSort(ElemType A[],int n) 2 { 3 int dk,i,j; 4 //前后记录位置的增量是dk,不是1 5 for (dk=n/2;dk>=1;dk=dk/2) 6 { 7 for (i=dk+1;i<=n;++i) 8 { 9 if (A[i]<A[i-dk]) 10 { 11 A[0]=A[i]; 12 for (j=i-dk;j>0 && A[0]<A[j];j-=dk) 13 A[j+dk]=A[j]; 14 A[j+dk]=A[0]; 15 } 16 } 17 } 18 }
参考书目:
王道考研系列
高分笔记系列