经典四讲贯通C++排序之二 希尔排序

开发 后端
经典四讲这四篇文章主要介绍C++数据结构排序知识,笔者把这四篇文章分为四个部分,分别介绍C++排序中插入排序、希尔排序、交换排序以及选择排序。本文是这次系列文章的第二篇,主要介绍希尔排序。

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

  希尔排序

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

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

  1. template <class T>  
  2. void ShellSort(T a[], int N, int& KCN, int& RMN)  
  3. {  
  4. KCN = 0; RMN = 0;  
  5. for (int gap = N/2; gap; gap = gap/2)  
  6. for (int i = gap; i < N; i++)  
  7. {  
  8. T temp = a[i]; RMN++;  
  9. for (int j = i; j >= gap && ++KCN && temp < a[j - gap]; j -= gap)  
  10. { a[j] = a[j - gap]; RMN++; }  
  11. a[j] = temp; RMN++;  
  12. }  

  测试结果:

  1. Sort ascending N=10000 TimeSpared: 0ms  
  2. KCN=120005 KCN/N=12.0005 KCN/N^2=0.00120005 KCN/NlogN=0.903128  
  3. RMN=240010 RMN/N=24.001 RMN/N^2=0.0024001 RMN/NlogN=1.80626  
  4. Sort randomness N=10000 TimeSpared: 10ms  
  5. KCN=258935 KCN/N=25.8935 KCN/N^2=0.00258935 KCN/NlogN=1.94868  
  6. RMN=383849 RMN/N=38.3849 RMN/N^2=0.00383849 RMN/NlogN=2.88875  
  7. Sort descending N=10000 TimeSpared: 10ms  
  8. KCN=172578 KCN/N=17.2578 KCN/N^2=0.00172578 KCN/NlogN=1.29878  
  9. RMN=302570 RMN/N=30.257 RMN/N^2=0.0030257 RMN/NlogN=2.27707 

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

  1. Sort ascending N=100000 TimeSpared: 140ms  
  2. KCN=1500006 KCN/N=15.0001 KCN/N^2=0.000150001KCN/NlogN=0.903094  
  3. RMN=3000012 RMN/N=30.0001 RMN/N^2=0.000300001RMN/NlogN=1.80619  
  4. Sort randomness N=100000 TimeSpared: 230ms  
  5. KCN=4041917 KCN/N=40.4192 KCN/N^2=0.000404192KCN/NlogN=2.43348  
  6. RMN=5598883 RMN/N=55.9888 RMN/N^2=0.000559888RMN/NlogN=3.37086  
  7. Sort descending N=100000 TimeSpared: 151ms  
  8. KCN=2244585 KCN/N=22.4459 KCN/N^2=0.000224459KCN/NlogN=1.35137  
  9. RMN=3844572 RMN/N=38.4457 RMN/N^2=0.000384457RMN/NlogN=2.31466 

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

【编辑推荐】

  1. 几种常用的C#排序方法简介
  2. 四种C#排序算法代码示例
  3. 希尔排序算法的JAVA实现
  4. c++编程常用工具
  5. 给C++初学者的50个忠告
  6. c++最基础的20条规则
  7. 深入剖析C/C++程序员应聘常见面试题
  8. 程序员必看 c++笔试题汇总
责任编辑:韩亚珊 来源: 天极网
相关推荐

2011-04-11 14:52:18

选择排序排序C++

2011-04-11 13:41:34

插入排序排序C++

2011-04-11 14:29:44

交换排序冒泡排序排序

2021-01-26 05:33:07

排序算法快速

2011-04-20 14:19:00

希尔排序

2011-04-11 15:57:22

DFSBFSC++

2011-04-11 16:19:56

C++

2023-03-06 08:10:52

数据结构算法数据

2022-03-12 20:12:08

希尔排序数组插入排序

2023-10-07 00:11:37

希尔排序算法

2011-04-11 16:32:28

路径C++

2021-01-19 07:02:26

算法数据结构堆排序

2011-04-11 16:10:55

无向图C++

2011-04-11 16:43:51

AOVAOE活动网络

2011-04-11 15:53:40

C++

2021-10-15 09:43:12

希尔排序复杂度

2011-04-20 13:56:08

选择排序

2021-01-21 05:22:36

排序算法选择

2010-02-06 16:16:01

C++冒泡排序

2009-09-08 17:20:01

C#排序算法
点赞
收藏

51CTO技术栈公众号