知識準備
基礎概念
希爾排序:在直接插入排序的基礎上進行的最佳化,直接插入排序在n值小的時候效率比較高,在n很大的時候如果待排序序列基本有序,效率依然很高,時間效率可以提升為O(n)。希爾排序也稱之為縮小增量排序。
1.先選取一個小於n的整數d(步長),然後按照步長d將待排序序列分為d組,從第一個記錄開始間隔為d的為一個組。然後對各組內進行直接插入排序,一趟過後,間隔為d的序列有序,隨著有序性的改善,減少步長d重複進行 。直到d=1使得間隔為1的記錄有序,也就達到了整體有序 步驟分解
1.我們有序列 18、 24、 12 、15 、1 、27、 17 、19。我們以步長為序列長度除以2作為第一次的步長。以後每次都在原有的步長基礎上除以2取整。直到步長為1後進行直接插入排序為止。
如上圖所示,我們把序列根據步長8/2=4,將序列分成四組分別為:
[1,18]、[24,27]、[12,17]、[15,19]。
然後對各組進行直接插入排序得到最後的結果:
1、24、12、15、18、27、17、19
2.繼續縮減步長,在上一步的結果序列1、24、12、15、18、27、17、19基礎上使得步長為上一步步長除以2,即步長為4/2=2重複第一步如下圖所示。
根據步長分為兩組,[1,12,17,18]、[15,19,24,27]然後分別執行直接插入排序獲得結果:
1、15、12、19、17、24、18、27
3.我們已經看到序列逐步成為有序的過程,知道最後步長為1,如當前執行個體。執行到第三步步長為2/2=1,所以進行最後一步的直接插入排序,序列就是有序序列了。
得到最終序列:
1、12、15、17、18、19、24、27
代碼實現
/** * 希爾排序 * * @param num */ public static void ShellSort(int num[]) { int temp; //預設步長為數組長度除以2 int step = num.length; while (true) { step = step / 2; //確定分組數 for (int i = 0; i < step; i++) { //對分組資料進行直接插入排序 for ( int j = i + step; j < num.length; j = j + step) { temp=num[j]; int k; for( k=j-step;k>=0;k=k-step){ if(num[k]>temp){ num[k+step]=num[k]; }else{ break; } } num[k+step]=temp; } } if (step == 1) { break; } } }
註:網路上有些希爾排序寫的稍微有點問題,把希爾排序裡面的直接插入寫成了冒泡了。