希爾排序(shell)

希爾排序O(nlogn)

希爾排序(Shell Sort)是插入排序的一種。也稱縮小增量排序,是直接插入排序算法的一種更高效的改進版本。希爾排序是非穩定排序算法。該方法因DL.Shell於1959年提出而得名。
希爾排序是把記錄按下標的一定增量分組,對每組使用直接插入排序算法排序;隨着增量逐漸減少,每組包含的關鍵詞越來越多,當增量減至1時,整個文件恰被分成一組,算法便終止。

優劣:

不需要大量的輔助空間,和歸併排序一樣容易實現。希爾排序是基於插入排序的一種算法, 在此算法基礎之上增加了一個新的特性,提高了效率。希爾排序的時間複雜度與增量序列的選取有關,例如希爾增量時間複雜度爲O(n²),而Hibbard增量的希爾排序的時間複雜度爲O(
  
),希爾排序時間複雜度的下界是n*log2n。希爾排序沒有快速排序算法快 O(n(logn)),因此中等大小規模表現良好,對規模非常大的數據排序不是最優選擇。但是比O(
  
)複雜度的算法快得多。並且希爾排序非常容易實現,算法代碼短而簡單。 此外,希爾算法在最壞的情況下和平均情況下執行效率相差不是很多,與此同時快速排序在最壞的情況下執行的效率會非常差。專家們提倡,幾乎任何排序工作在開始時都可以用希爾排序,若在實際使用中證明它不夠快,再改成快速排序這樣更高級的排序算法. 本質上講,希爾排序算法是直接插入排序算法的一種改進,減少了其複製的次數,速度要快很多。 原因是,當n值很大時數據項每一趟排序需要的個數很少,但數據項的距離很長。當n值減小時每一趟需要和動的數據增多,此時已經接近於它們排序後的最終位置。 正是這兩種情況的結合才使希爾排序效率比插入排序高很多。Shell算法的性能與所選取的分組長度序列有很大關係。只對特定的待排序記錄序列,可以準確地估算關鍵詞的比較次數和對象移動次數。想要弄清關鍵詞比較次數和記錄移動次數與增量選擇之間的關係,並給出完整的數學分析,至今仍然是數學難題。

時間性能

1.增量序列的選擇
Shell排序的執行時間依賴於增量序列。
好的增量序列的共同特徵:
① 最後一個增量必須爲1;
② 應該儘量避免序列中的值(尤其是相鄰的值)互爲倍數的情況。
有人通過大量的實驗,給出了較好的結果:當n較大時,比較和移動的次數約在nl.25到1.6n1.25之間。
2.Shell排序的時間性能優於直接插入排序
希爾排序的時間性能優於直接插入排序的原因:
①當文件初態基本有序時直接插入排序所需的比較和移動次數均較少。
②當n值較小時,n和
  
的差別也較小,即直接插入排序的最好時間複雜度O(n)和最壞時間複雜度0(
  
)差別不大。
③在希爾排序開始時增量較大,分組較多,每組的記錄數目少,故各組內直接插入較快,後來增量di逐漸縮小,分組數逐漸減少,而各組的記錄數目逐漸增多,但由於已經按di-1作爲距離排過序,使文件較接近於有序狀態,所以新的一趟排序過程也較快。
因此,希爾排序在效率上較直接插入排序有較大的改進。
由於visualgo上沒有希爾排序的視頻,我只能在這裏簡單舉個例子了。。。。。(爲毛你沒有希爾的)


arr[] = {5, 4, 3, 2, 1};

5 / 2 = 2;

 5  4    3 2

1A        1A       1A

      2A       2A


一樣字母的是一組,歸爲一組後進行插入排序,

1 3 4 5

由於取的數字實在是很特殊經過一次希爾排序就成功了。


for (int gap = num/2;gap > 0;gap /= 2) {
	for (int i = 0;i < gap;i++) {
		for (int j = i+gap;j < num;j+=gap) {
			if (arr[j] < arr[j-gap]) {
				int temp = arr[j];
				int k = j - gap;
				while (k >= 0 && arr[k] > temp)  {  
                        	   arr[k + gap] = arr[k];  
                        	   k -= gap;  
                    	        }  
                    	arr[k + gap] = temp;
			}
		}
	}
}

稍微改進一下

for (int gap = num / 2; gap > 0; gap /= 2)
	for (int j = gap; j < num; j++)
		if (arr[j] < arr[j - gap]){
			int temp = arr[j];
			int k = j - gap;
			while (k >= 0 && arr[k] > temp)
			{
				arr[k + gap] = arr[k];
				k -= gap;
			}
			arr[k + gap] = temp;
	        }






















發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章