您的位置:首页 > 其它

排序算法(四) —— 希尔排序

2016-12-13 14:04 405 查看

 

1.     和直接插入排序的关系

 

  在之前直接插入排序中提到过,希尔排序(Shell sort)是直接插入排序的变种方式之一,是一种更高效的改进版本。其基本思想如下:

  • 记录按下标的一定增量分组,对每组进行直接插入排序。
  • 不断地缩小增量,对每组进行直接插入排序,直至增量为1。

 

  由此可见,希尔排序本质就是多次使用直接插入排序。其优于直接插入排序的原因在之前也提到过,就是:直接插入排序对于基本有序的数组,拥有较高的性能。

 

  希尔入排序的时间复杂度是O(n^2)(只是针对最坏情况而言,平均的效率要远远高出其他时间复杂度为O(n^2)的排序算法),空间复杂度是O(1),但是在提供优秀性能的同时,打破了排序算法的稳定性。

 

  直接插入排序:http://www.cnblogs.com/jing-an-feng-shao/p/6165094.html

 

 

2.     希尔排序的实现

 

  希尔排序,又称缩小增量排序,其重点显然在于初始增量 d 的选取,以及每次增量 d 缩小的额度。一般来说,初始增量设为数组长度的一半,同时每次增量减半,直至 d=1,可以满足大多数的需求。

 

  下面用一个具体的场景,直观地体会一下希尔排序的过程。

场景:

现有一个无序数组,共7个数:89 45 54 29 90 34 68。

使用希尔排序法,对这个数组进行升序排序。

 

初始数组:

89 45 54 29 90 34 68

第一步:增量 d=3

29 45 34 68 90 54 89

第二步:增量 d=1

29 34 45 54 68 89 90

 

希尔排序的 Java 代码实现:

1     public static void main(String[] args) {
2
3         final int size = 100000;
4         // 模拟数组
5         int[] array = new int[size];
6         for (int i = 0; i < array.length; i++) {
7             array[i] = new Random().nextInt(size) + 1;
8         }
9
10         // 时间输出:纳秒
11         long s1 = System.nanoTime();
12         Shell.basal(array);
13         long e1 = System.nanoTime();
14         System.out.println(e1 - s1);
15     }
test

 

执行结果:

 

结论如下:

  • 直接插入排序的优化手段,对希尔排序没有作用,反而是一种伤害。原因在直接插入排序中提到过:其优化手段对于小规模的数组是有害的。而希尔排序的原理是将整个数组拆成若干个小数组,利用直接插入排序对基本有序的数组拥有良好的性能这一特性出发的。
  • 同样是不稳定排序,对比直接插入排序的二分查找优化,无论数组规模的大小,希尔排序在性能上都有明显的优势。

 

 

相关链接:

https://github.com/Gerrard-Feng/Algorithm/blob/master/Algorithm/src/com/gerrard/sort/Shell.java

 

PS:如有描述不当之处,欢迎指正!

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: