算法熟记-排序系列-希尔排序

1. 简述

    假设待排序数组为 int array[], 数组长度为n。
    该方法实质上是一种分组插入方法。假设数组长度n=10,我们设定几个分组的个数为1,3,5。
    首先,分5组,即(array[0],array[5]),
                          (array[1],array[6]),
                          (array[2],array[7]),
                           ...,每组内部进行插入排序
    然后,分3组,即(array[0],array[3],array[6],array[9]),
                          (array[1],array[4],array[7]),

                          (array[2],array[5],array[8]), 每组内部进行插入排序
    最后,分1组,即array[0], array[1], ... , array[9], 进行插入排序 

2. 复杂度

    希尔排序是对普通插入排序的改进,之所以是改进,是因为,普通插入排序在插入的时候往往需要移动大量的数据,而分组,使得数组相对有序,移动的步长也有提示,不再是1了,因此会有效率上的提高,具体的证明不是很简单,也就不深究了。
由于是多次分组插入排序,是非稳定的排序。
     O(n log n) 如果使用最佳的现在版本,但是具体怎么算出来的,确实不清楚。

3. 代码

    有了前面插入排序的代码,这个代码理解起来就容易多了。
    这里给出一个java中的代码,感觉代表性很强,也容易理解。   

void  shellsort ( int [] a,  int  n)
 {
     
int  i, j, k, temp, gap;
     // 预先证明的合理的分组方法
     
int [] gaps  =  {  1 , 5 , 13 , 43 , 113 , 297 , 815 , 1989 , 4711 , 11969 , 27901 , 84801 ,
                    
213331 , 543749 , 1355339 , 3501671 , 8810089 , 21521774 ,
                    
58548857 , 157840433 , 410151271 , 1131376761 , 2147483647  }; 
     // 根据n计算,分组个数
      for  (k = 0 ; gaps[k] < n; k ++ ) ; 
      while  ( -- >=   0 ) {
         gap 
=  gaps[k]; 
         
for  (i = gap; i < n; i ++){  //  因为是插入排序,当然是从第一组的第二个元素开始,即i=gap
             temp 
=  a[i];
             j 
=  i;
             
while  (j >= gap  &&  a[j - gap] > temp) {
                 a[j] 
=  a[j - gap];
                 j 
=  j - gap;
             }
             a[j] 
=  temp;
         }
     }
 }

    关于分组方法,简单的可以使用3*i+1的方法产生,直到n/2,比如对于n=10,就是1,4。尽量要求分组个数之间没有公约数。也有一些经过证明的方法。

4. 参考资料

    维基百科-希尔排序  
    http://en.wikipedia.org/wiki/Shell_sort
    http://zh.wikipedia.org/wiki/%E5%B8%8C%E5%B0%94%E6%8E%92%E5%BA%8F

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值