数据结构——插入排序

 一、直接插入排序

1、直接插入排序的算法思想:

R[i] 的键值Ki与R[0]…R[i-1]的键值依次比较(从后往前比),找到R[i]应插入的位置,并把从该位置开始的记录后移一个位置,把R[i] 插入到找到的插入位置,完成一趟直接排序;重复选R[i+1]….. R[n]完成上述操作,直到排序完毕 。

注:为什么要从后往前比?可以在比较的同时将需要向后移动的元素向后面挪位。

2、算法:

Void zjcrpx(JD r[],int n)
  { int i,j;
    for (i=2;i<=n;i++){
       r[0]=r[i];          /*将待插元素设为监视哨*/
       j=i-1;              /*从有序区的最后一个开始比*/
       while (r[0].key<r[j].key) {
            r[j+1]=r[j];
            j--;
            }/*查找R[i]的插入位置,将关键字大于R[i] .key的记录依次后移*/
            r[j+1]=r[0];      /*插入待插元素*/ 
            }
       } 
} 
注:什么是监视哨?监视哨往往是程序里面的一个变量,如果是对数字排序的话,那么该变量一般是数值型变量。变量的赋值就相当于哨兵,当排序数列中出现与哨兵相等的值或有某种既定关系出现时,就做一种操作,比如说停止排序,或进行下一趟排序。

3、直接插入排序算法中监视哨的作用:

(1)备份:进入查找循环(找R[i]的插入位置)之前,保存了R[i]的副本,这样就不会因记录的后移而丢失R[i]的内容。

(2)监视比较(即j)是否越界:一旦越界,自动控制循环结束,从而避免了在while循环内的每一次比较都要检测j是否越界(使测试循环条件的时间大约减少一半)。

4、直接插入排序算法分析:

从空间来看,只需要一个记录的辅助空间;
从时间来看,排序的基本操作为:比较两个关键字的大小和移动记录,o(n2)。

稳定性:稳定排序。

二、二分法排序

1、排序策略:

R1,R2,…,Ri-1已经排序,用二分法找出Ri(第i个记录)的插入位置,并把键值Ki( Ri 的关键码)的记录后移一个位置,空出位置插入Ri记录。

2、二分法插入排序的算法思想:

(1)若Ki<Km(即:r[I].key<r[m].key),则在[R1,R2,…,Rm-1]区间再二分查找插入位置,否则;

(2)若Ki>Km(即:r[I].key>r[m].key),则在[Rm+1,Rm+2,…,Ri-1]区间再二分查找插入位置;
如此重复,直到找到插入位置。
(3)把从该位置开始的记录后移一个位置,把R[i] 插入到找到的插入位置,完成一次排序;重复选R[i+1]….. R[n]完成上述操作,直到排序完毕 。

3、算法

void binarysort(JD r[],int n)
{    int i,j;
     for(i=2;i<=n;i++)
     { r[0]=r[i];
       int low=1;      
       int  high=i-1;
       while(low<=high)
            { mid=(low+high)/2;
              if(r[0].key<r[mid].key)
                  high=mid-1;
              else 
                  low=mid+1;
             }
       for(j=i-1;j>=low;j--) r[j+1]=r[j];
       r[low]=r[0];
       } 
 }
4、二分法插入排序算法分析:

从空间来看:只需要一个记录的辅助空间;
从时间来看:在上面的算法中,每插入一个Ri,平均比较次数为log2i,减少了关键字间的比较次数,但记录的移动次数不变。因此二分插入排序的时间复杂度仍是o(n2)。
稳定性: 稳定性排序 。

三、Sell(希尔)排序

1、希尔排序思想方法:
(1)先取一个正整数d1<n(例如: d1 =n/2),把全部记录分成d1个组,所有距离为d1倍数的记录放在同一个组中,并在各组内进行直接插入排序;
(2)取d2< d1(例如:d2=d1/2)重复上述分组和排序,直到di= 1( di< di-1<…< d2< d1 ),即所有记录放在一个组中为止。

2、Shell排序中增量di的取法:
      如何选择di才能产生最好的排序效果,这涉及到许多数学问题(至今未得到完全解决), Shell本人提出,取:d1=n/2,d2=d1/2,…..,di=1,平均比较次数和平均移动次数为n1.3左右,且排序是不稳定的。

3、算法:

 void shellpx(JD r[],int n)
       {JD x;  
       int i,j,k;
       k=n/2;
       while(k>=1){
              for (i=k+1;i<=n;i++)
                 {x=r[i];
                 j=i-k;
                 while ((j>0)&&(x.key<r[j].key))
                   {r[j+k]=r[j];j=j-k;}
                 r[j+k]=x;
                 }
               k=k/2;
              }
}
4、希尔排序算法分析

由两种循环构成,外循环是增量由n/2逐步缩小到1的循环,for所构成的循环是针对某一特定的增量k,进行大跨步踊跃式的插入排序(按增量分组进行组内插入排序)。例如,当k=2时,关键字被分为两组。当K=1时,此算法等同于直接插入排序,由于前面大增量的处理,使关键字大体有序,因此最后一趟排序移动的记录少,处理速度快。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值