1. 程式人生 > >演算法第四記-希爾排序

演算法第四記-希爾排序

作者: dreamcatcher-cx

出處: <http://www.cnblogs.com/chengxiao/>

本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段宣告,且在頁面明顯位置給出原文連結。

 

希爾排序是希爾(Donald Shell)於1959年提出的一種排序演算法。希爾排序也是一種插入排序,它是簡單插入排序經過改進之後的一個更高效的版本,也稱為縮小增量排序,同時該演算法是衝破O(n2)的第一批演算法之一。本文會以圖解的方式詳細介紹希爾排序的基本思想及其程式碼實現。

基本思想

  希爾排序是把記錄按下標的一定增量分組,對每組使用直接插入排序演算法排序;隨著增量逐漸減少,每組包含的關鍵詞越來越多,當增量減至1時,整個檔案恰被分成一組,演算法便終止。

  簡單插入排序很循規蹈矩,不管陣列分佈是怎麼樣的,依然一步一步的對元素進行比較,移動,插入,比如[5,4,3,2,1,0]這種倒序序列,陣列末端的0要回到首位置很是費勁,比較和移動元素均需n-1次。而希爾排序在陣列中採用跳躍式分組的策略,通過某個增量將陣列元素劃分為若干組,然後分組進行插入排序,隨後逐步縮小增量,繼續按組進行插入排序操作,直至增量為1。希爾排序通過這種策略使得整個陣列在初始階段達到從巨集觀上看基本有序,小的基本在前,大的基本在後。然後縮小增量,到增量為1時,其實多數情況下只需微調即可,不會涉及過多的資料移動。

  我們來看下希爾排序的基本步驟,在此我們選擇增量gap=length/2,縮小增量繼續以gap = gap/2的方式,這種增量選擇我們可以用一個序列來表示,{n/2,(n/2)/2...1},稱為增量序列

。希爾排序的增量序列的選擇與證明是個數學難題,我們選擇的這個增量序列是比較常用的,也是希爾建議的增量,稱為希爾增量,但其實這個增量序列不是最優的。此處我們做示例使用希爾增量。

void shell_Sort(int arr[], int length)
{
	int gap = length / 2;
	while (gap)
	{
		for (int i = gap; i < length; i++)//用於序列gap插入一次
		{
			int j = i - gap;
			int value = arr[i];
			while (j>=0&&value<arr[j])
			{
				arr[j+gap] = arr[j];//5 3 6 7 2 1 0
				j -= gap;
			}
			arr[j + gap] = value;
		}
		gap /= 2;
	}
}

   由於多次插入排序,我們知道一次插入排序是穩定的,不會改變相同元素的相對順序,但在不同的插入排序過程中,相同的元素可能在各自的插入排序中移動,最後其穩定性就會被打亂,所以shell排序是不穩定的。

   本文介紹了希爾排序的基本思想及其程式碼實現,希爾排序中對於增量序列的選擇十分重要,直接影響到希爾排序的效能。我們上面選擇的增量序列{n/2,(n/2)/2...1}(希爾增量),其最壞時間複雜度依然為O(n2),一些經過優化的增量序列如Hibbard經過複雜證明可使得最壞時間複雜度為O(n3/2)。希爾排序的介紹到此為止,關於其他排序演算法的介紹也會陸續更新,謝謝支援。