1. 程式人生 > >演算法學習筆記--希爾排序

演算法學習筆記--希爾排序

希爾排序:這是一種基於插入排序的快速的排序演算法。
這種排序的主要思想就是:使陣列中任意間隔為h的元素都是有序的,這樣的陣列稱為h有序陣列

如下圖,就是一個h有序陣列(h=4):
這裡寫圖片描述

實現希爾排序的方法就是對於每一個h,用插入排序的方式,將h個子陣列獨立排序,然後逐漸減小h的值,直到h=1。

java程式碼如下:

/**
 * 希爾排序
 */
public class Shell {

    public static void sort(int[] a){

        int N = a.length;
        int h = 1;
        while(h < N/3
){ // h = 1/2(3^k - 1) 1, 4, 13, 40, 121, 364, 1093, ... h = 3*h + 1; // 選取合適的遞增數列可以提高演算法效能 這裡使用Algorithms一書中推薦的遞增數列 } while(h >=1){ for (int i = h; i < N; i++) { for (int j = i; j >= h && (a[j] < a[j-h]); j -= h) { int
temp = a[j]; a[j] = a[j-h]; a[j-h] = temp; } } h = h/3; } } }

軌跡圖:

這裡寫圖片描述

在上述程式碼中,使用了序列1/2(3^k-1),從N/3開始逐漸減至1。這種序列稱之為遞增序列。選擇合理的遞增序列將提高演算法的效能。

特點:
這種排序非常的高效,因為它平衡了子陣列的規模和有序性。
和選擇排序以及插入排序相比,希爾排序也可用於大型陣列,對任意排序的陣列表現也很好。





小彩蛋:
最近發現了一個有趣的交換的方法,不增加新的變數來交換a b兩個變數的值

a = a ^ b; 
b = a ^ b;  //實際上是(a^b)^b 也就是a異或了b兩次,等號右邊是a的值
a = a ^ b;  //此時b裡面已經是“果汁”,實際上是(a^b)^a,也就是b異或了a兩次,是b

所以上述程式碼中交換可以換成下面這樣。

    a[j] = a[j]^a[j-h];
    a[j-h] = a[j]^a[j-h];
    a[j] = a[j]^a[j-h];

這樣寫立刻顯得逼格滿滿啊 逃)。




這裡寫圖片描述