上一篇介紹了希爾排序,它又被稱為縮小增量排序,這就說明了增量在希爾排序中的重要性。
本篇使用四組不同的增量,通過統計排序的比較次數、移動次數、執行時間,來討論不同的增量對希爾排序效率的影響。
選取的增量:h1=N/2, N/4, N/8,……,1(每次增量減半)
h2=N/3, N/9, N/27,……,1(每次增量為原來的三分之一)
h3=2ⁿ-1 (h=1,3,7,……)(增量為奇數)
h4=(3ⁿ-1)/2 (h=1,4,13,……)
1、保持序列元素個數不變
保持序列元素個數為1000000,每次隨機生成不同的序列,對四個增量分別做4組排序。
增量h | 比較次數 | 移動次數 | 執行時間(ms) | 平均時間(ms) |
h1 | 70899317 | 53401514 | 390 | 409 |
71248646 | 53751082 | 437 | ||
63125216 | 45628028 | 406 | ||
65709200 | 48211399 | 406 | ||
h2 | 58908538 | 47827463 | 328 | 367 |
57271566 | 46192005 | 360 | ||
58745050 | 47664214 | 422 | ||
58158118 | 47077871 | 359 | ||
h3 | 63337835 | 45942623 | 391 | 434 |
62261484 | 44866301 | 422 | ||
64507400 | 47112762 | 485 | ||
65932139 | 48537533 | 438 | ||
h4 | 67600938 | 56206667 | 359 | 398 |
62428374 | 51034112 | 390 | ||
67867685 | 56472626 | 453 | ||
63794589 | 52400141 | 391 |
從測試的結果來看,當序列元素個數相同時,對四種增量分別用生成的四組隨機數排序時,它們的比較次數、移動次數以及執行時間等參數差別不大。因此可以認為對於待排序列的元素個數相同的情況下,基於以上四種增量的序列,希爾排序算法的時間復雜度差異不是很明顯,執行效率差別不大。
2、序列的元素個數改變
使序列元素個數增加,分別取10000、100000、1000000、10000000,每次隨機生成不同的序列,對四個增量分別排序。
元素個數 | 增量h | 比較次數 | 移動次數 | 執行時間(ms) |
10000 | h1 | 266301 | 151388 | 0 |
h2 | 242150 | 171389 | 0 | |
h3 | 237881 | 129346 | 15 | |
h4 | 238686 | 167816 | 0 | |
100000 | h1 | 4270009 | 2820476 | 32 |
h2 | 4174584 | 3267076 | 15 | |
h3 | 3959590 | 2543037 | 32 | |
h4 | 3867292 | 2941534 | 31 | |
1000000 | h1 | 66890878 | 49393622 | 422 |
h2 | 59190877 | 48110274 | 360 | |
h3 | 59872906 | 42478486 | 406 | |
h4 | 62805422 | 51410564 | 375 | |
10000000 | h1 | 1035250229 | 820261049 | 5301 |
h2 | 1167560154 | 1036812889 | 5532 | |
h3 | 980127157 | 772150177 | 5294 | |
h4 | 9659604955 | 854508598 | 5378 |
從測試結果可以看出,不同長度的序列使用四個增量分別進行排序時,比較次數、移動次數、排序時長有一定差異。當元素個數較少時,增量為h2=N/3, N/9, N/27,……,1的希爾排序效率比其他增量略高;
當元素個數較多時,增量為h4=(3ⁿ-1)/2 (h=1,4,13,……)的希爾排序效率比其他增量略高。
綜上所述,希爾排序算法在不同增量下的執行效率也不盡相同,增量是影響希爾排序效率的重要因素。遺憾的是,雖然有很多論文專門研究過不同的增量對希爾排序的影響,但都無法證明某個增量是最好的。因此在使用希爾排序時,根據排序序列的大小,選取適當的增量對提高排序效率很有幫助。
參考代碼:以Java為例。
import java.util.Random; /* * 希爾排序 */ public class ShellSort { //增量h=N/2 static long comp1 = 0; //比較次數 static long exch1 = 0; //交換次數 public static void sort1(int[] a) { int n = a.length; //序列長度 int h = n/2; //初始增量h為序列長度的一半 while (h >= 1) { for (int i = h; i < n; i++) { for (int j = i; j >= h; j -= h) { comp1++; if(a[j]<a[j-h]){ int swap = a[j]; a[j] = a[j-h]; a[j-h] = swap; exch1++; }else{ break; } } } h /= 2; //增量減半 } } //增量h=N/3 static long comp2 = 0; //比較次數 static long exch2 = 0; //交換次數 public static void sort2(int[] a) { int n = a.length; //序列長度 int h = n/3; //初始增量h為序列長度的三分之一 while (h >= 1) { for (int i = h; i < n; i++) { for (int j = i; j >= h; j -= h) { comp2++; if(a[j]<a[j-h]){ int swap = a[j]; a[j] = a[j-h]; a[j-h] = swap; exch2++; }else{ break; } } } h /= 3; //增量減為三分之一 } } //增量h=2ⁿ-1 (h=1,3,7……) static long comp3 = 0; //比較次數 static long exch3 = 0; //交換次數 public static void sort3(int[] a) { int n = a.length; //序列長度 int h = 1; while (h < n/2) h = 2*h + 1; while (h >= 1) { for (int i = h; i < n; i++) { for (int j = i; j >= h; j -= h) { comp3++; if(a[j]<a[j-h]){ int swap = a[j]; a[j] = a[j-h]; a[j-h] = swap; exch3++; }else{ break; } } } h /= 2; } } //增量h=(3ⁿ-1)/2 (h=1,4,13……) static long comp4 = 0; //比較次數 static long exch4 = 0; //交換次數 public static void sort4(int[] a) { int n = a.length; //序列長度 int h = 1; while (h < n/3) h = 3*h + 1; while (h >= 1) { for (int i = h; i < n; i++) { for (int j = i; j >= h; j -= h) { comp4++; if(a[j]<a[j-h]){ int swap = a[j]; a[j] = a[j-h]; a[j-h] = swap; exch4++; }else{ break; } } } h /= 3; } } public static void main(String[] args) { Random random = new Random(); int[] arg = new int[10000]; for(int n=0;n<10000;n++){ //從[0-10000]中生成10000個隨機數 arg[n] = random.nextInt(10000); } int[] arg1 = new int[arg.length]; int[] arg2 = new int[arg.length]; int[] arg3 = new int[arg.length]; int[] arg4 = new int[arg.length]; for(int n=0;n<arg.length;n++){ //將隨機生成的數組復制到4個數組中 arg1[n] = arg[n]; arg2[n] = arg[n]; arg3[n] = arg[n]; arg4[n] = arg[n]; } //分別對4個元素相等的數組用4個不同增量排序 long startTime1 = System.currentTimeMillis(); //獲取開始時間 sort1(arg1); long endTime1 = System.currentTimeMillis(); //獲取結束時間 long startTime2 = System.currentTimeMillis(); //獲取開始時間 sort2(arg2); long endTime2 = System.currentTimeMillis(); //獲取結束時間 long startTime3 = System.currentTimeMillis(); //獲取開始時間 sort3(arg3); long endTime3 = System.currentTimeMillis(); //獲取結束時間 long startTime4 = System.currentTimeMillis(); //獲取開始時間 sort4(arg4); long endTime4 = System.currentTimeMillis(); //獲取結束時間 System.out.println("數組長度:"+arg.length); System.out.println("增量h=N/2的比較次數: "+comp1+" 交換次數:"+exch1+" 排序時長:"+(endTime1-startTime1)+"ms"); System.out.println("增量h=N/3的比較次數: "+comp2+" 交換次數:"+exch2+" 排序時長:"+(endTime2-startTime2)+"ms"); System.out.println("增量h=2ⁿ-1的比較次數: "+comp3+" 交換次數:"+exch3+" 排序時長:"+(endTime3-startTime3)+"ms"); System.out.println("增量h=(3ⁿ-1)/2的比較次數:"+comp4+" 交換次數:"+exch4+" 排序時長:"+(endTime4-startTime4)+"ms"); } }
執行結果:
數組長度:10000 增量h=N/2的比較次數: 265465 交換次數:150579 排序時長:0ms 增量h=N/3的比較次數: 230360 交換次數:159712 排序時長:0ms 增量h=2ⁿ-1的比較次數: 238035 交換次數:129679 排序時長:15ms 增量h=(3ⁿ-1)/2的比較次數:227429 交換次數:156614 排序時長:0ms
轉載請注明出處 http://www.cnblogs.com/Y-oung/p/7805984.html
工作、學習、交流或有任何疑問,請聯系郵箱:yy1340128046@163.com