排序 : 2 插入排序

2 插入排序

a直接插入排序

直接插入排序(Straight Insertion Sorting)的基本思想是:把n个待排序的元素看成为一个有序表和一个无序表,开始时有序表中只包含一个元素,无序表中包含有n-1个元素,排序过程 中每次从无序表中取出第一个元素,将它插入到有序表中的适当位置,使之成为新的有序表,重复n-1次可完成排序过程。
把a[i]插入到a[0],a[1],...,a[i-1]之中的具体实施过程为:先把a[i]赋值给变量t,然后将t依次与a[i-1],a[i- 2],...进行比较,将比t大的元素右移一个位置,直到发现某个j(0<=j<=i-1),使得a[j]<=t或j为(-1),把t 赋值给a[j+1].

一趟直接插入排序方法
1.简单方法

     首先在当前有序区R[1..i-1]中查找R[i]的正确插入位置k(1≤k≤i-1);然后将R[k..i-1]中的记录均后移一个位置,腾出k位置上的空间插入R[i]。
  注意:
     若R[i]的关键字大于等于R[1..i-1]中所有记录的关键字,则R[i]就是插入原位置。


//插入排序,只排序从下标1开始的数列,下标为0的位置用来存放小哨兵,以防止数组越界

  for(int i=2;i<ints.length;i++){//要插入的元素

   int j=i-1; //记录已排好序的数列的最后一个元素

   ints[0]=ints;//复制为小哨兵,防止数组越界

   while(ints<ints[j]){//寻找插入点

    --j;

   }

   for(int n=i-1;n>=j;n--){//为插入点腾出位置

    ints[n+1]=ints[n];

   }

   ints[j]=ints[0];//插入要插入的元素

  }

此算法最好情况是本来已排好序,需要比较n-1次,复制小哨兵n-1次,时间复杂度为O(n)。最坏情况是每次都需要向前插入,需要比较1+2+3+...+n-1次,需要移动n+1+2+3+...+n-1次,因此时间复杂度为O(n的平方)。不管有多少元素,不需要额处空间,空间复杂度为O(1).相等的数不可能交换位置,因此此算法是稳定的。



2.改进的方法
  一种查找比较操作和记录移动操作交替地进行的方法。
具体做法:
     将待插入记录R[i]的关键字从右向左依次与有序区中记录R[j](j=i-1,i-2,…,1)的关键字进行比较:
     ① 若R[j]的关键字大于R[i]的关键字,则将R[j]后移一个位置;
      ②若R[j]的关键字小于或等于R[i]的关键字,则查找过程结束,j+1即为R[i]的插入位置。
     关键字比R[i]的关键字大的记录均已后移,所以j+1的位置已经腾空,只要将R[i]直接插入此位置即可完成一趟直接插入排序。

    void InsertionSort(ElementTpe A[ ],int N )

{

 int j,P;

 ElementType Tem;

 for(p=1;p<N;p++)

  {

   tem=A[P];

   for(j=P;j>0&&A[j-1]>Tem;j--)

       A[j]=A[j-1];

  A[j]=tem;

  }

}


b希尔排序(缩小增量排序)----不稳定

该方法的基本思想是:先将整个待排元素序列分割成若干个子序列(由相隔某 个“增量”的元素组成的)分别进行直接插入排序,然后依次缩减增量再进行排序,待整个序列中的元素基本有序(增量足够小)时,再对全体元素进行一次直接插 入排序。因为直接插入排序在元素基本有序的情况下(接近最好情况),效率是很高的,因此希尔排序在时间效率上比前两种方法有较大提高。
具体做法:首先确定一组增量d0,d1,d2,d3,...,dt-1()其中n>d0>d1>...>dt-1=1),对于 i=0,1,2,...,t-1,依次进行下面的各趟处理:根据当前增量di将n个元素分成di个组,每组中元素的下标相隔为di;再对各组中元素进行直 接插入排序.

        给定实例的shell排序的排序过程
     假设待排序文件有10个记录,其关键字分别是:
        49,38,65,97,76,13,27,49,55,04。
     增量序列的取值依次为:
        5,3,1
     排序过程如【动画模拟演示】。


算法分析

1.增量序列的选择

     Shell排序的执行时间依赖于增量序列。
     好的增量序列的共同特征:
  ① 最后一个增量必须为1;
  ② 应该尽量避免序列中的值(尤其是相邻的值)互为倍数的情况。
     有人通过大量的实验,给出了目前较好的结果:当n较大时,比较和移动的次数约在nl.25到1.6n1.25之间。

2.Shell排序的时间性能优于直接插入排序
     希尔排序的时间性能优于直接插入排序的原因:
  ①当文件初态基本有序时直接插入排序所需的比较和移动次数均较少。
  ②当n值较小时,n和n2的差别也较小,即直接插入排序的最好时间复杂度O(n)和最坏时间复杂度0(n2)差别不大。
  ③在希尔排序开始时增量较大,分组较多,每组的记录数目少,故各组内直接插入较快,后来增量di逐渐缩小,分组数逐渐减少,而各组的记录数目逐渐增多,但由于已经按di-1作为距离排过序,使文件较接近于有序状态,所以新的一趟排序过程也较快。
     因此,希尔排序在效率上较直接插人排序有较大的改进。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值