1. 程式人生 > >算法:希爾排序

算法:希爾排序

org any 小數 wiki 增加 mini for num 循環

算法:希爾排序

快速開始

百科解釋

  希爾排序(Shell‘s Sort)是插入排序的一種又稱“縮小增量排序”(Diminishing Increment Sort),是直接插入排序算法的一種更高效的改進版本。希爾排序是非穩定排序算法。該方法因D.L.Shell於1959年提出而得名。

  希爾排序是基於插入排序的以下兩點性質而提出改進方法的:

    • 插入排序在對幾乎已經排好序的數據操作時,效率高,即可以達到線性排序的效率
    • 但插入排序一般來說是低效的,因為插入排序每次只能將數據移動一位

補充:各種常用排序算法的復雜度分析:

  技術分享圖片

主要思想

  原始的算法實現在最壞的情況下需要進行O(n

2)的比較和交換。V. Pratt的書[1]對算法進行了少量修改,可以使得性能提升至O(n log2n)。這比最好的比較算法的O(n log n)要差一些。

  希爾排序通過將比較的全部元素分為幾個區域來提升插入排序的性能這樣可以讓一個元素可以一次性地朝最終位置前進一大步。然後算法再取越來越小的步長進行排序,算法的最後一步就是普通的插入排序,但是到了這步,需排序的數據幾乎是已排好的了(此時插入排序較快)

  假設有一個很小的數據在一個已按升序排好序的數組的末端。如果用復雜度為O(n2)的排序(冒泡排序或插入排序),可能會進行n次的比較和交換才能將該數據移至正確位置。而希爾排序會用較大的步長移動數據,所以小數據只需進行少數比較和交換即可到正確位置。

  一個更好理解的希爾排序實現:將數組列在一個表中並對列排序(用插入排序)。重復這過程,不過每次用更長的列來進行。最後整個表就只有一列了。將數組轉換至表是為了更好地理解這算法,算法本身僅僅對原數組進行排序(通過增加索引的步長,例如是用i += step_size而不是i++)。

實例說明

  顏色相同表示根據步長被劃分到同一批次中。同一批次中的元素進行插入排序,這樣一個元素很有可能將朝著最終位置前進一大步。到最後可見需排列的數據幾乎已經拍好了。但是也正是由於數組元素大小及位置關系的不確定性,導致了該算法是不穩定的。

  技術分享圖片

Java實現代碼

package com.company.sort;

public class shellSort {
    public static void main(String[] args)
    {
        int[] arr= { 13,14, 94, 33 ,82 ,25 ,59 ,94 ,65, 23 ,45 ,27, 73, 25, 39, 10};
        shell_sort(arr);
    }

    public static void shell_sort(int[] arr) {
        //gap 為步長...
        int gap = 1, i, j, len = arr.length;
        int temp;
        //步長計算方式不唯一
        while (gap < len / 3)
            gap = gap * 3 + 1; // <O(n^(3/2)) by Knuth,1973>: 1, 4, 13, 40, 121, ...

        for (; gap > 0; gap /= 3)
            //步長不斷縮小,最後為1
            for (i = gap; i < len; i++) {
                //取出第i個元素
                temp = arr[i];
                //從第i個元素開始,與之前每次步長為gap的元素進行比較
                for (j = i - gap; j >= 0 && arr[j] > temp; j -= gap)
                    arr[j + gap] = arr[j]; //如果前者元素大於後者,則互換位置
                arr[j + gap] = temp; //因為上面循環最後一次比較j仍會減gap,所以還要補償回來gap
            }

            for(int num:arr)
                System.out.println(num);
    }
}

  

算法:希爾排序