排序算法之希爾排序


希爾排序

    先將整個待排序的序列分割成若干個子序列分別進行直接插入排序,當整個序列的元素“基本有序”時,再對全體進行一次直接插入排序。

需要注意的是,子序列的構成不是簡單的“逐段分割”,而是將相隔某個“增量”的記錄組成一個子序列,如第一趟增量爲5,第二趟增量可以爲3等等。

    這個增量習慣上用字母h來表示這個增量, 常用的h序列由Knuth提出,該序列從1開始,通過如下公式產生:h = 3 * h +1。

例如下述過程:

6708432236718c02636f8cc6f4e3fde3.jpg

希爾排序穩定性

希爾排序是不穩定的算法,它滿足穩定算法的定義。對於相同的兩個數,可能由於分在不同的組中而導致它們的順序發生變化。

希爾排序時間複雜度

希爾排序的時間複雜度與增量(即步長gap)的選取有關。如,當增量爲1時,希爾排序退化爲直接插入排序,此時的時間複雜度爲0(N),而Hibbard增量的希爾排序的時間複雜度爲0(N^3/2)。


Java實現

package acm;
/*希爾排序
 * 2017.11.22
 * 希爾排序算法減小數據項的間隔再進行排序,依次進行下去,進行這些排序時的數據項
 *  之間的間隔被稱爲增量,習慣上用字母h來表示這個增量。
 * 常用的h序列由Knuth提出,該序列從1開始,通過如下公式產生:h = 3 * h +1
*/
public class ShellSort {
     
     static void shellSort(int[] ary){
          int h = 1;
          //計算h可取的最大值
          while(h <= ary.length/3){
              h = 3*h+1;
          }         
          while(h>0){
              for(int i=h;i<ary.length;i+=h){
                   if(ary[i]<ary[i-h]){
                        int temp = ary[i];
                        int j = i-h;
                        while(j>=0 && ary[j]>temp){
                             ary[j+h] = ary[j];
                             j-=h;
                        }
                        ary[j+h] = temp;
                        for(int ele:ary){
                             System.out.print(ele+",");
                        }
                        System.out.println("");//換行
                   }    
              }
              h = (h-1)/3;
          }
          
     }
     public static void main(String[] args){
          int[] ary = new int[]{49,38,65,97,76,13,27,49,55,4};
          shellSort(ary);
     }
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章