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

排序演算法——希爾排序

希爾排序是1959 年由D.L.Shell提出來的,相對直接排序有較大的改進。希爾排序又叫縮小增量排序

基本思想

先將整個待排序的記錄序列分割成為若干子序列分別進行直接插入排序,待整個序列中的記錄“基本有序”時,再對全體記錄進行依次直接插入排序。

演算法

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

這裡寫圖片描述

我們簡單處理增量序列

:增量序列d = {n/2 ,n/4, n/8…..1} n為要排序數的個數

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

Code

JAVA:

package sort;

import java.util.Arrays;

public class ShellSort {
    public static void main(String[] args) {
        int
a[] = {49,38,65,97,76,13,27,49,55,4}; shellSort(a); System.out.println(Arrays.toString(a)); } public static void shellSort(int[] arr) { int j = 0; int tmp = 0; int n = arr.length; for (int d = n/2; d >0; d /= 2) { System.out.println("increment:"
+ d); for (int i = d; i<n ; i ++) { tmp = arr[i]; j = i-d; while (j>=0 && tmp < arr[j]) { arr[j+d] = arr[j];//元素右移 j -= d; } arr[j+d] = tmp; } System.out.println(Arrays.toString(arr)); } } }

result:

increment:5
[13, 27, 49, 55, 4, 49, 38, 65, 97, 76]
increment:2
[4, 27, 13, 49, 38, 55, 49, 65, 97, 76]
increment:1
[4, 13, 27, 38, 49, 49, 55, 65, 76, 97]
[4, 13, 27, 38, 49, 49, 55, 65, 76, 97]

Python

a = [49,38,65,97,76,13,27,49,55,4]

def Shell_sort(arr):
    tmp = 0
    n = len(arr)
    d = int(n/2)
    while d>0:
        d = int(d/2)
        print("Increment: %d" %d)
        for i in range(d,n):
            tmp = arr[i]
            j = i-d
            while j>=0 and tmp < arr[j]:
                arr[j+d] = arr[j]
                j -= d
            arr[j+d] = tmp
        print(arr)
    return arr

print(Shell_sort(a))

時效

希爾排序的關鍵並不是隨便分組後各自排序,而是將相隔某個“增量”的記錄組成一個子序列,實現跳躍式移動,使得排序的效率提高。需要注意的是,增量序列的最後一個增量值必須等於1才行。另外,由於記錄是跳躍式的移動,希爾排序是一種不穩定的的排序演算法。
希爾排序最好時間複雜度和平均時間複雜度都是O(nlogn),最壞時間複雜度為O(n^2)

參考