排序问题——折半插入排序

1、算法思想

关于查找的讨论中可知,对于有序表进行折半查找,其性能有越于顺序查找。所以可以将折半查找思想用于在有序记录r[1...i-1]中确定应插入的位置,相应的算法排序称为折半插入算法。

算法的基本过程:


   1)计算 0 ~ i-1 的中间点,用 i 索引处的元素与中间值进行比较,如果 i 索引处的元素大,说明要插入的这个元素应该在中间值和刚加入i索引之间,反之,就是在刚开始的位置 到中间值的位置,这样很简单的完成了折半;


   2)在相应的半个范围里面找插入的位置时,不断的用(1)步骤缩小范围,不停的折半,范围依次缩小为 1/2  1/4  1/8 .......快速的确定出第 i  个元素要插在什么地方;


   3)确定位置之后,将整个序列后移,并将元素插入到相应位置。

C描述:

/***折半插入排序***/
/*算法原理:从第二个数开始逐个置入监视哨,使用low,high标签在L[0..i-1]有序区内进行折半查找
来确认待排序数的插入位置,然后将该位置到最后一个数全部后移一位,最后腾出该位置,
把监视哨里面的数置入该位置。后面的数以此类推进行排序,直到最后一个数比较完毕。
*/
#include<stdio.h>
void  binaryInsertSort( int  L[], int  n)
{
     int  i,j;
     int  low,high,mid;
     //用L[0]作为监视哨,L[1..i-1]为有序区,
     for (i=2;i<=n;i++)
     {
         L[0]=L[i];       //待排序的数进监视哨
         low=1;
         high=i-1;        //初始化low,high
         while (low<=high) //循环语句确定插入位置,必须保证low<=high
         {
             mid=(low+high)/2;
             if (L[0]<L[mid]) //根据L[0]的值的大小,确定属于低半区还是高半区
                 high=mid-1; //插入低半区//插入低半区
             else
                 low=mid+1; //插入高半区
         }
         for (j=i-1;j>=high+1;j--) //待插入位置后面L[hign+1..i-1]全部数后移一位
             L[j+1]=L[j];
         L[high+1]=L[0];      //或者换成L[j+1]=L[0];监视哨里面的数插入数组
     }
}
 
void  binaryInsertSort1( int  L[], int  n)
{
     int  i,j;
     int  low,high,mid,tmp;
     //用临时变量tmp作为监视哨,L[0..i-1]为有序区
     for (i=1;i<n;i++)
     {
         tmp=L[i];
         low=0;
         high=i-1;
         while (low<=high)
         {
             mid=(low+high)/2;
             if (tmp<L[mid])
                 high=mid-1;
             else
                 low=mid+1;
         }
         for (j=i-1;j>=high+1;j--)
             L[j+1]=L[j];
         L[high+1]=tmp;
     }
}
 
int  main()
{
     int  i,n;
     int  a[50];
     printf ( "输入n= " );
     scanf ( "%d" ,&n);
     printf ( "输入数组元素:\n" );
//  for(i=1;i<=n;i++)
     for (i=0;i<n;i++)
         scanf ( "%d" ,&a[i]);
//  binaryInsertSort(a,n);
     binaryInsertSort1(a,n-1);
     printf ( "排序后;\n" );
//  for(i=1;i<=n;i++)
     for (i=0;i<n;i++)
         printf ( "%-4d" ,a[i]);
     putchar (10);
     return  0;
}

算法分析:

采用折半插入排序法,可减少关键字的比较次数。每插入一个元素,需要比较的次数最大的折半判定树的深度,如插入第i个元素时,设i=2的j次方,则需要进行以2为底i的对数次比较,因此插入n-1个元素的平均关键字的比较次数为n倍的以2为底的n的对数。当n较大时,折半插入排序法的比较次数比直接插入排序的最差情况要好很多,但要比其最好情况差。

虽然折半插入排序法与直接插入排序法相比较,改善了算法中比较次数的数量级,但其并未改变移动元素的时间耗费,所以折半插入排序的总时间复杂度仍然是O(n*n).


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值