c++语言编程希尔排序法排序,经典四讲贯通C++排序之二 希尔排序

我们都知道C++排序方法中,有四种常用方法插入排序、希尔排序、交换排序以及选择排序。上一篇文章,我们介绍了插入排序,今天我们介绍另一种排序方法――希尔排序。(本系列文章统一 测试程序)

希尔排序

前面的算法的平均效率都不怎么好,但我们注意到直插排序在关键码基本有序的情况下,效率是最好的,并且,在关键码的数量很少的时候,n和n2的差距也不是那么的明显。基于以上的事实,D.L.Shell在1959年(老古董了)提出了缩小增量排序,基本思想是:取一个间隔(gap),将序列分成若干的子序列,对每个子序列进行直插排序;然后逐渐缩小间隔,重复以上过程,直到间隔为1。在开始的时候,每个子序列里关键码很少,直插的效率很高;随着间隔的缩小,子序列的关键码越来越多,但是在前面的排序基础上,关键码已经基本有序,直插的效率依然很高。

希尔排序的时间复杂度不好估量,gap的选取也没有定论,gap=[gap/2]的程序是最好写的,至于为什么,写写就知道了。template

voidShellSort(T a[],intN,int& KCN,int& RMN)

{

KCN = 0; RMN = 0;

for(intgap = N/2; gap; gap = gap/2)

for(inti = gap; i 

{

T temp = a[i]; RMN++;

for(intj = i; j >= gap && ++KCN && temp 

{ a[j] = a[j - gap]; RMN++; }

a[j] = temp; RMN++;

}

}

测试结果:Sort ascending N=10000 TimeSpared: 0ms

KCN=120005 KCN/N=12.0005 KCN/N^2=0.00120005 KCN/NlogN=0.903128

RMN=240010 RMN/N=24.001 RMN/N^2=0.0024001 RMN/NlogN=1.80626

Sort randomness N=10000 TimeSpared: 10ms

KCN=258935 KCN/N=25.8935 KCN/N^2=0.00258935 KCN/NlogN=1.94868

RMN=383849 RMN/N=38.3849 RMN/N^2=0.00383849 RMN/NlogN=2.88875

Sort descending N=10000 TimeSpared: 10ms

KCN=172578 KCN/N=17.2578 KCN/N^2=0.00172578 KCN/NlogN=1.29878

RMN=302570 RMN/N=30.257 RMN/N^2=0.0030257 RMN/NlogN=2.27707

注意到这时的测试结果很不准确了,10000个整数的排序已经测试不出什么来了(估计新机器都是0ms,我这里也有个别的时候全是0)。因此,下面用100000个整数的排序重新测试了一次:Sort ascending N=100000 TimeSpared: 140ms

KCN=1500006 KCN/N=15.0001 KCN/N^2=0.000150001KCN/NlogN=0.903094

RMN=3000012 RMN/N=30.0001 RMN/N^2=0.000300001RMN/NlogN=1.80619

Sort randomness N=100000 TimeSpared: 230ms

KCN=4041917 KCN/N=40.4192 KCN/N^2=0.000404192KCN/NlogN=2.43348

RMN=5598883 RMN/N=55.9888 RMN/N^2=0.000559888RMN/NlogN=3.37086

Sort descending N=100000 TimeSpared: 151ms

KCN=2244585 KCN/N=22.4459 KCN/N^2=0.000224459KCN/NlogN=1.35137

RMN=3844572 RMN/N=38.4457 RMN/N^2=0.000384457RMN/NlogN=2.31466

这个结果表明,希尔排序几乎没有最坏情况,无论是正序、逆序、乱序,所用时间都不是很多,附加储存是O(1),的确非常不错。在没搞清楚快速排序、堆排序之前,它的确是个很好的选择,我当年一直用它。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值