1. 程式人生 > >插入排序算法之希爾排序

插入排序算法之希爾排序

back ... 步長 i++ 作用 運行時間 參考 ack bar

一、前沿:

希爾排序(Shell Sort)的名稱源於它的發明者Donald Shell,該算法是沖破了二次元時間屏障的算法之一。它通過比較相距一定間隔的元素工作,各趟所用的距離隨著算法的進行而減小,直到只比較相鄰元素的最後一趟為止,因此希爾排序有時也叫做縮減增量排序(diminishing increament sort)。

二、詳細步驟:

希爾排序使用一個序列h1,h2,......ht 叫做 增量序列,只要h1=1,任何增量序列都是可行的,在使用hk的一趟增量序列後,數組中任何a[i]<=a[i+k]是有意義的。所有相隔k的元素都是有序的,此時稱之為數組是hk

有序的。下圖為希爾排序每趟後的情況:

技術分享圖片

hk排序的一般做法是,對於hk,hk+1.......N-1中的每一個位置i,把其上的元素放置在i,i-hk,i-2hk,.....中的正確位置上。雖然並不影響最終結果,但通過觀察可發現,一趟hk排序的作用就是對hk個獨立的子數組執行一次插入排序,在分析希爾排序的運行時間時,這個觀測結果是很重要的!!

三、算法實現

在考慮到增量序列的問題中,可以通過ht=[n/2]和hk=[hk+1/2]。也可以通過自己設定增量序列來實現:

 1     /**
 2      * 希爾排序是簡單插入排序的改進版,突破了復雜度為O(n*n)的排序算法,它與插入排序不同的是
3 * ,它會優先比較距離較遠的元素,它又叫縮小增量排序 4 */ 5 public static void shellSort1(int[] r, int low, int high, int[] delta) { 6 for (int k = 0; k < delta.length; k++) 7 shellInsert(r, low, high, delta[k]); //一趟步長為 delta[k]的直接插入排序 8 } 9 //shellInsert 執行的是插入排序 10 private
static void shellInsert(int[] r, int low, int high, int deltaK) { 11 for (int i = low + deltaK; i <= high; i++) 12 if (r[i]<r[i-deltaK]) { 13 //小於時,需將 r[i] 插入有序表,執行的過程跟插入排序一樣 14 int temp = r[i]; 15 int j ; 16 for (j= i - deltaK; j >= low && temp < r[j]; j = j - deltaK) 17 r[j + deltaK] = r[j]; //記錄後移 18 r[j + deltaK] = temp; //插入到正確位置 19 System.out.println(Arrays.toString(r)); 20 } 21 22 23 }

四、時間復雜度分析

希爾排序的運行時間依賴於增量序列的選擇,希爾排序的平均情形分析,除最平凡的一些增量序列外,是一個長期未曾解決的問題。我們將對希爾排序的最壞情況分析:

1、使用希爾增量時希爾排序的最壞情形運行時間為O(n2

2、使用Hibbard增量的希爾排序的最壞情況運行時間為O(n3/2):證明略

實踐中,大多數希爾排序的運行時間為O(n3/2

五、參考資料

《數據結構與算法分析》

插入排序算法之希爾排序