希爾排序是先將整個待排元素序列分割成若干個子序列(由相隔某個“增量”的元素組成的)分別進行直接插入排序,然後依次縮減增量再進行排序,待整個序列中的元素基本有序(增量足夠小)時,再對全體元素進行一次直接插入排序。因為直接插入排序在元素基本有序的情況下(接近最好情況),效率是很高的,因此希爾排序在時間效率上比前兩種方法有較大提高。
以n=10的一個數組49, 38, 65, 97, 26, 13, 27, 49, 55, 4為例
第一次 gap = 10 / 2 = 5
49 38 65 97 26 13 27 49 55 4
1A 1B
2A 2B
3A 3B
4A 4B
5A 5B
1A,1B,2A,2B等為分組標記,數字相同的表示在同一組,大寫字母表示是該組的第幾個元素, 每次對同一組的資料進行直接插入排序。即分成了五組(49, 13) (38, 27) (65, 49) (97, 55) (26, 4)這樣每組排序後就變成了(13, 49) (27, 38) (49, 65) (55, 97) (4, 26),下同。
第二次 gap = 5 / 2 = 2
排序後
13 27 49 55 4 49 38 65 97 26
1A 1B 1C 1D 1E
2A 2B 2C 2D 2E
第三次 gap = 2 / 2 = 1
4 26 13 27 38 49 49 55 97 65
1A 1B 1C 1D 1E 1F 1G 1H 1I 1J
第四次 gap = 1 / 2 = 0 排序完成得到數組:
4 13 26 27 38 49 49 55 65 97
例子:
<?php/** * 希爾排序 */function shell_sort(array $arr){ // 將$arr按升序排列 $len = count($arr); $f = 3;// 定義因子 $h = 1;// 最小為1 while ($h < intval($len/$f)){ $h = $f*$h + 1; // 1, 4, 13, 40, 121, 364, 1093, ... } while ($h >= 1){ // 將數組變為h有序 echo '<br>'.'h:'.$h.'<br>'.'<br>'; for ($i = $h; $i < $len; $i++){ // 將a[i]插入到a[i-h], a[i-2*h], a[i-3*h]... 之中 (演算法的關鍵 echo 'i:'.$i.'<br>'; for ($j = $i; $j >= $h && $arr[$j] < $arr[$j-$h]; $j -= $h){ $temp = $arr[$j]; $arr[$j] = $arr[$j-$h]; $arr[$j-$h] = $temp; dump($arr); } } $h = intval($h/$f); } return $arr;}$arr = array(14, 9, 1, 4, 6, -3, 2, 99, 13, 20, 17, 15, 3);dump($arr);$shell = shell_sort($arr);echo '<pre>';print_r($shell);function dump($arr){foreach ($arr as $value) {echo $value.' ';}echo '<br>';}
結果:
14 9 1 4 6 -3 2 99 13 20 17 15 3
h:4
i:4
6 9 1 4 14 -3 2 99 13 20 17 15 3
i:5
6 -3 1 4 14 9 2 99 13 20 17 15 3
i:6
i:7
i:8
6 -3 1 4 13 9 2 99 14 20 17 15 3
i:9
i:10
i:11
6 -3 1 4 13 9 2 15 14 20 17 99 3
i:12
6 -3 1 4 13 9 2 15 3 20 17 99 14
6 -3 1 4 3 9 2 15 13 20 17 99 14
3 -3 1 4 6 9 2 15 13 20 17 99 14
h:1
i:1
-3 3 1 4 6 9 2 15 13 20 17 99 14
i:2
-3 1 3 4 6 9 2 15 13 20 17 99 14
i:3
i:4
i:5
i:6
-3 1 3 4 6 2 9 15 13 20 17 99 14
-3 1 3 4 2 6 9 15 13 20 17 99 14
-3 1 3 2 4 6 9 15 13 20 17 99 14
-3 1 2 3 4 6 9 15 13 20 17 99 14
i:7
i:8
-3 1 2 3 4 6 9 13 15 20 17 99 14
i:9
i:10
-3 1 2 3 4 6 9 13 15 17 20 99 14
i:11
i:12
-3 1 2 3 4 6 9 13 15 17 20 14 99
-3 1 2 3 4 6 9 13 15 17 14 20 99
-3 1 2 3 4 6 9 13 15 14 17 20 99
-3 1 2 3 4 6 9 13 14 15 17 20 99
Array( [0] => -3 [1] => 1 [2] => 2 [3] => 3 [4] => 4 [5] => 6 [6] => 9 [7] => 13 [8] => 14 [9] => 15 [10] => 17 [11] => 20 [12] => 99)