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 basal(int[] array) { 2 if (array == null || array.length < 2) { 3 return; 4 } 5 // 初始增量 6 int d = array.length >>> 1; 7 while (d > 0) { 8 // d 次直接插入排序 9 for (int i = 0; i < d; i++) { 10 // 组内进行,相隔增量 d 项的直接插入排序 11 for (int j = i + d; j < array.length; j += d) { 12 int cur = array[j]; 13 boolean flag = false; 14 for (int k = j - d; k > -1; k -= d) { 15 if (cur < array[k]) { 16 array[k + d] = array[k]; 17 } else { 18 array[k + d] = cur; 19 flag = true; 20 break; 21 } 22 } 23 if (!flag) { 24 array[i] = cur; 25 } 26 } 27 } 28 // 每次增量减半 29 d >>>= 1; 30 } 31 }