最近回顧了一下 《The C Programming Language》,其中提到了一個用來演示 for 迴圈的小例子,如下:
/** shell sort */
void shellsort(int[], int);
int main()
{
int a[] = {1,23,34,24,32,25,31,3,36,40};
int b[] = {32,31,30,29,28,27,26,25,24,23};
shellsort(b, 10);
}
void shellsort(int v[], int n)
{
int gap, i, j, temp;
for(gap = n/2; gap > 0; gap /= 2) {
for(i = gap; i<n; i++) {
for(j=i-gap; j>=0 && v[j] > v[j+gap]; j-=gap) {
temp = v[j];
v[j] = v[j+gap];
v[j+gap] = temp;
}
}
}
}
這是一個希爾排序的例子,以每次 n/2 為步長,比較步長兩邊的元素的大小,步長是從大到小的,也就是說,一開始直接比較相距較遠的兩個元素,如果是逆序,則直接交換,比基於相鄰比較的排序(氣泡排序,交換排序)跨越了更多的中間位置;然後最終步長為1能夠保證所有元素都能正確被排序。步長為1時,退化為交換排序,但是其實這時序列是已經經過排序的,所以要比一開始就用交換排序要好。
希爾排序是第一批跨越 O(n2) 複雜度的排序演算法之一。它是一種不穩定的排序演算法,其效能與步長的取值有很大關係,Wikipedia上有關於各種步長選擇下的效能比較:Shellsort#Gap_sequences。
為了幫助理解希爾排序的排序過程,可以看這個演示視訊(需FQ): Shell Sort Algorithm Example
PS:個人部落格連結 – 理解希爾排序