希尔(Shell)排序

align="center" marginwidth="0" marginheight="0" src="http://xviewee.googlepages.com/adsTop.html" frameborder="0" width="468" scrolling="no" height="60"> 
希尔(Shell)排序
相信大家如果学过数据结构与算法的话,一定对希尔排序有很深的印象吧,个人最喜欢的排序就是希尔排序了,希尔排序相对于其他算法的实现来说比较简单,而且效率也还可以,没有选择法、插入排序及冒泡排序的O(n 2)平方级时间复杂度,但当然也没有线性排序算法的O(n)级的线性时间复杂度,对于大型数据输入,线性算法肯定是最佳的选择,但对于中规模数据而言,希尔排序无疑是最佳的选择。算法大师Knuth在他的著作<<计算机程序设计艺术>>给出的希尔排序的平均时间复杂度为O(n 1.3),介于平方级和线性级之间。
如果你知道插入排序,就很容易理解其排序思想,他的做法是:先取一个整数d 1<n,把全部纪录分成d 1个组,所有距离为d 1倍数的记录放在一组中,先在各组内排序;然后取d ­2­<d ­1­重复上述分组和排序工作;直到d ­i­=1,即所有记录放在一组中为止。各组的排序可以采用直接插入法,也可以采用像直接选择排序或堆排序等其他排序方法。
直接插入排序在输入序列基本有序时,排序时间较少。另一方面,当n值较小时,n和n ­­ 2的差别也较小。Shell排序开始时增量较大,分组较多,每组的记录数目较少,故在各组内采用直接插入排序较快,后来增量d ­­­ i 逐渐缩小,分组数减少,各组的记录数增多,但由于已经按d­ i-1­分组排序,序列已经趋于有序态,所以一趟排序过程也较快。因此,Shell排序在效率上比直接排序有较大的改进。。
希尔排序的实现:
Void ShellSort(SortObject * pvector , int d)
{
         int i,j,increment;
         RecordNode temp;
         for (increment = d ; increment > 0 ; increment /= 2)
         {
                   for ( i = increment ; i < pvector->n; i ++ )
                   {
                            temp = pvector->record[i];                                            //保存待插入元素
                            j = i - increment;
                            while ( j >= 0 && temp.key < pvector->record[j].key)//对每组进行插入排序
                            {
                                     pvector->record[j+increment] = pvector->record[j];
                                     j -= increment;
                            }
                            if (j != i - increment) pvector->record[ j + increment ] = temp;
                   }
         }
}
希尔排序示例:
 
初始序列:         49     ,        38     ,        65     ,        97     ,        13     ,        76     ,        27     ,        49
 
Increment=4:
①I = 4 , temp.key = 13 , j = 0,交换49和13:
13 , 38 , 65 , 97 , 49 , 76 , 27 , 49
②I = 5 , temp.key = 76 , j = 1,不交换38和76:
 13 , 38 , 65 , 97 , 49 , 76 , 27 , 49
③ I = 6, temp.key = 27 , j = 2,交换65和27: 
13 , 38 , 27 , 97 , 49 , 76 , 65, 49
④ I = 7, temp.key = 49 , j = 3,交换97和49 :
 13 , 38 , 65 ,49 , 49 , 76 , 27 , 97
 
 
 
Increment=2:
①I = 2 , temp.key = 27 , j = 0, 不交换13和27:
13 , 38 , 65 ,49 , 49 , 76 , 27 , 97
②I =3 , temp.key = 49 , j = 1,不交换38和49 :
13 , 38 , 65 ,49 , 49 , 76 , 27 , 97
③ I = 4, temp.key = 49 , j = 2,交换65和27: 
13 , 38 , 65 ,49 , 49 , 76 , 27 , 97
④ I =5, temp.key = 76 , j = 3,交换97和49 :
 13 , 38 , 65 ,49 , 49 , 76 , 27 , 97
⑤I = 6, temp.key = 65 , j = 2,交换65和27: 
13 , 38 , 65 ,49 , 49 , 76 , 27 , 97
⑥I = 7, temp.key = 97 , j = 3,交换97和49 :
13 , 38 , 65 ,49 , 49 , 76 , 27 , 97
 
 
Increment = 1:
同插入排序
最后得:
13      ,        27     ,        38     ,        49’      ,        49     ,        65     ,        76     ,        97
 
如果仔细分析算法的每一步,我们可以看到对于增量划分的每一组数据,不是将分别对每一组数据进行插入排序,而是从各组交替进行插入排序的,从increment+1下标元素开始顺序遍历至最后一个元素,对每一个元素和他前面已成有序态的同一组数据进行插入排序。。
 
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值