排序之插入排序学习总结

插入排序:对一个待排记录序列,按关键字的大小插入到前面已排好序的子序列,直至全部记录插入完成。

这里写图片描述

1.直接插入排序

这里写图片描述
将A[i]插入到A[k]位置:

void InsertSort_Direct(ElemType A[ ],int n)
{
   int i,k;        //k表示最后插入位置
   for(i=2;i<=n;i++)      //对第2-n个元素遍历
   {
      if(A[i]<A[i-1])
      {
          A[0]=A[i];       //A[i]暂存到A[0]
          for(k=i-1;A[k]>A[0];k--)      //找到值大于A[i]的一堆元素,向后移动
              A[k+1]=A[k];
           k++;      //找到插入位置k
           A[k]=A[0];      //将A[i]的值复制A[k]
       }
   }
}

分析
(1)空间复杂度O(1),因为只使用了常数个辅助单元;
(2)时间效率
   ①最好情况:原列有序排列,比较次数为:n-1次,不需移动元素,时间复杂度:O(n);
   ①最坏情况:原列逆序排列, 比较次数为:0+1+2+…+n-1=n(n-1)/2次,时间复杂度:O(n^2);
(3)稳定(因为总是从后向前比较再移动,不会改变元素的相对位置);
(4)适用于顺序及链式结构。

2.折半插入排序

思想:若排序表采用顺序结构存储时,对有序子表采用折半查找,查找出待插元素位置k(=high+1),再将A[k]…A[i-1]向后移动,最后将元素A[i]插入A[k]位置。

举例如下:
在这里插入图片描述

void InsertSort_Binary(ElemType A[],int n)
{
    int low,high;      //折半查找插入位置时的指针
   for(int i=2;i<=n;i++)
	{
	     if(A[i]<A[i-1])
	     {
	         A[0]=A[i];     //将A[i]复制到A[0]
	                         //开始进行折半查找
	         low=1;
	         high=i-1;    //A[1]~A[i-1]为有序子列
	         while(low<=high)
	         {
	         int mid=(low+high)/2;
	         if(A[mid]>A[0])   //说明插入位置在mid左方
	               high=mid-1;
	          else      //说明插入位置在mid右方
	               low=mid+1;
	           }
	           for(int j=i-1;j>=high+1;j--)   //元素依次后移
	                A[j+1]=A[j];
	           A[high+1]=A[0];    //将A[i]插入
	     }
	}
}

分析
(1)时间复杂度O(n^2);
(2)稳定

3.希尔排序(缩小增量排序)

思想:将L[1…n]表划分为L[i,i+d,i+2d,…,i+kd]的特殊子表,分别进行直接插入排序;当整个表基本有序时,再对整个表进行一次直接插入排序。

举例分析:
在这里插入图片描述
分析
(1)空间复杂度O(1),因为只使用了常数个辅助单元;
(2)最坏情况:时间复杂度O(n^2);
(2)不稳定(相同的关键字被划分到不同的子表时,元素相对位置可能发生改变);
(4)适用于顺序存储。

发布了28 篇原创文章 · 获赞 13 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/pilgrim_121/article/details/79539910