標籤:估算 使用 情況 樣本 技術 下標 strong 實現 .sh
希爾排序是1959 年由D.L.Shell 提出來的,相對直接排序有較大的改進。希爾排序又叫縮小增量排序
基本思想:
先將整個待排序的記錄序列分割成為若干子序列分別進行直接插入排序,待整個序列中的記錄“基本有序”時,再對全體記錄進行依次直接插入排序。
操作方法:
- 選擇一個增量序列t1,t2,…,tk,其中ti>tj,tk=1;
- 按增量序列個數k,對序列進行k 趟排序;
- 每趟排序,根據對應的增量ti,將待排序列分割成若干長度為m 的子序列,分別對各子表進行直接插入排序。僅增量因子為1 時,整個序列作為一個表來處理,表長度即為整個序列的長度。
希爾排序的樣本:
演算法實現:
我們簡單處理增量序列:增量序列d = {n/2 ,n/4, n/8 .....1} n為要排序數的個數
即:先將要排序的一組記錄按某個增量d(n/2,n為要排序數的個數)分成若干組子序列,每組中記錄的下標相差d.對每組中全部元素進行直接插入排序,然後再用一個較小的增量(d/2)對它進行分組,在每組中再進行直接插入排序。繼續不斷縮小增量直至為1,最後使用直接插入排序完成排序。
1 /** 2 * 3 * @author zhangtao 4 */ 5 public class ShellInsertSort 6 { 7 public static void main(String[] args) 8 { 9 int arr[]={49,38,65,97,76,13,27,49,55,4};10 shellSort(arr);11 }12 13 /** 14 * 直接插入排序的一般形式 15 * @param int dk 縮小增量,如果是直接插入排序,dk=1 16 * 17 */ 18 static void shellInsertSort(int a[], int dk) 19 { 20 int n=a.length;21 for(int i= dk; i<n; ++i){ 22 if(a[i] < a[i-dk]){ //若第i個元素大於i-1元素,直接插入。小於的話,移動有序表後插入 23 int j = i-dk; 24 int x = a[i]; //複製為哨兵,即儲存待排序元素 25 a[i] = a[i-dk]; //首先後移一個元素 26 while(x < a[j]){ //尋找在有序表的插入位置 27 a[j+dk] = a[j]; 28 j -= dk; //元素後移 29 if(j<0)30 {31 break;32 }33 } 34 a[j+dk] = x; //插入到正確位置 35 } 36 printLine(a, i ); 37 } 38 } 39 40 /** 41 * 先按增量d(n/2,n為要排序數的個數進行希爾排序 42 */ 43 static void shellSort(int a[]){ 44 int n=a.length;45 int dk = n/2; 46 while( dk >= 1 ){ 47 shellInsertSort(a, dk); 48 dk = dk/2; 49 } 50 } 51 52 //列印每次的排序結果53 static void printLine(int[] arr,int i)54 {55 System.out.println(i+":");56 int Arrlength=arr.length;57 for(int j=0;j<Arrlength;j++)58 {59 System.out.print(arr[j]+" ");60 }61 System.out.println();62 }63 }
希爾排序時效分析很難,關鍵碼的比較次數與記錄移動次數依賴於增量因子序列d的選取,特定情況下可以準確估算出關鍵碼的比較次數和記錄的移動次數。目前還沒有人給出選取最好的增量因子序列的方法。增量因子序列可以有各種取法,有取奇數的,也有取質數的,但需要注意:增量因子中除1 外沒有公因子,且最後一個增量因子必須為1。希爾排序方法是一個不穩定的排序方法。
插入排序—希爾排序(Shell`s Sort)原理以及Java實現