演算法學習筆記--希爾排序
阿新 • • 發佈:2019-02-08
希爾排序:這是一種基於插入排序的快速的排序演算法。
這種排序的主要思想就是:使陣列中任意間隔為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];
這樣寫立刻顯得逼格滿滿啊 逃)。