希爾排序

希爾排序

希爾排序的實質就是分組插入排序,該方法又稱縮小增量排序,因DL.Shell於1959年提出而得名。


描述 

基本思想是:先將整個待排元素序列分割成若干個子序列(由相隔某個“增量”的元素組成的)分別進行直接插入排序,然後依次縮減增量再進行排序,待整個序列中的元素基本有序(增量足夠小)時,再對全體元素進行一次直接插入排序。因爲直接插入排序在元素基本有序的情況下(接近最好情況),效率是很高的。

圖示:


操作方法:

  1. 選擇一個增量序列t1,t2,…,tk,其中ti>tj,tk=1;
  2. 按增量序列個數k,對序列進行k 趟排序;
  3. 每趟排序,根據對應的增量ti,將待排序列分割成若干長度爲m 的子序列,分別對各子表進行直接插入排序。僅增量因子爲1 時,整個序列作爲一個表來處理,表長度即爲整個序列的長度。
算法:

我們簡單處理增量序列:增量序列d = {n/2 ,n/4, n/8 .....1} n爲要排序數的個數

即:先將要排序的一組記錄按某個增量dn/2,n爲要排序數的個數)分成若干組子序列,每組中記錄的下標相差d.對每組中全部元素進行直接插入排序,然後再用一個較小的增量(d/2)對它進行分組,在每組中再進行直接插入排序。繼續不斷縮小增量直至爲1,最後使用直接插入排序完成排序。

package com.zq.algorithm.sort;

/**
 * Created by zhengshouzi on 2015/11/1.
 */
public class ShellSort {
    public static void main(String[] args) {
        int[] a = {70,30,40,10,80,20,90,100,75,60,45};
        shellSort(a);
    }
    public static  void shellSort(int[] a){
        //d的初始增量
        int d=a.length/2;
        //int d =a.length/3;
        int count=0;
        while (d>=1){
            count++;
            for (int i = d; i <a.length ; i++) {
                //交換
                if (a[i]<a[i-d]){
                    //記住需要插入的值
                    int j = i-d;
                    int temp = a[i];
                    //往前找插入位置
                    //“j>=0”表示最後插入位置在第一個位置時候不再循環,“temp<a[j]”第一次循環肯定要進入,接着不斷改變j的值,判斷待插入的值與之前的每一個值那個大,並把比較的值向後移動d位,直到找到插入位置。
                    while (j>=0&&temp<a[j]){
                        a[j+d] = a[j];
                        j-=d;//j的變化速度應該和增量一樣,因爲每一插入都是正對子序列插入排序
                    }
                    //插入
                    a[j+d]=temp;
                }
            }
            System.out.print("第: "+count+" 趟 增量爲:"+d+" 排序爲 :");
            for (int i = 0; i <a.length ; i++) {
                System.out.print(" " + a[i]);
            }
            System.out.println();
            //控制增量,在這裏,有多種控制增量的方法d =d/3等等
            d=d/2;
           /* if (d==3){
                d=2;
            }else {
                d=d/2;
            }*/

        }
        System.out.println("最終結果:");
        for (int i = 0; i <a.length ; i++) {
            System.out.print(" " + a[i]);
        }
        System.out.println();
    }
}

結果如下:



將代碼中控制增量部分的註釋去掉,將原來的控制增量部分註釋掉,出現如下結果,可以和上面的  圖示進行對比



希爾排序時效分析很難,關鍵碼的比較次數與記錄移動次數依賴於增量因子序列d的選取,特定情況下可以準確估算出關鍵碼的比較次數和記錄的移動次數。目前還沒有人給出選取最好的增量因子序列的方法。增量因子序列可以有各種取法,有取奇數的,也有取質數的,但需要注意:增量因子中除1 外沒有公因子,且最後一個增量因子必須爲1。希爾排序方法是一個不穩定的排序方法。





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