Java實現希爾排序


  希爾排序(Shell Sort)是插入排序的一種,是針對直接插入排序算法的改進,是將整個無序列分割成若干小的子序列分別進行插入排序,希爾排序並不穩定。該方法又稱縮小增量排序,因DL.Shell於1959年提出而得名。

一、基本思想

  先取一個小於n的整數d1作為第一個增量,把文件的全部記錄分成d1個組。所有距離為d1的倍數的記錄放在同一個組中。先在各組內進行直接插入排序;然后,取第二個增量d2<d1重復上述的分組和排序,直至所取的增量dt=1(dt<dt-l<…<d2<d1),即所有記錄放在同一組中進行直接插入排序為止。

二、下面讓我們看一下希爾排序的一個實例:

三、希爾排序的時間性能優於直接插入排序的原因:
     ①當文件初態基本有序時直接插入排序所需的比較和移動次數均較少。
     ②當n值較小時,n和n2的差別也較小,即直接插入排序的最好時間復雜度O(n)和最壞時間復雜度0(n2)差別不大。
     ③在希爾排序開始時增量較大,分組較多,每組的記錄數目少,故各組內直接插入較快,后來增量di逐漸縮小,分組數逐漸減少,而各組的記錄數目逐漸增多,但由於已經按di-1作為距離排過序,使文件較接近於有序狀態,所以新的一趟排序過程也較快。
        因此,希爾排序在效率上較直接插人排序有較大的改進。
       

增量序列的選擇:Shell排序的執行時間依賴於增量序列。好的增量序列的共同特征(查到的資料都這么講): 

     ① 最后一個增量必須為1;
     ② 應該盡量避免序列中的值(尤其是相鄰的值)互為倍數的情況。 
     

四、具體的java代碼實現

 

public static void shellSort(int[] a){
		double gap = a.length;//增量長度
		int dk,sentinel,k;
		while(true){
			gap = (int)Math.ceil(gap/2);//逐漸減小增量長度
			dk = (int)gap;//確定增量長度 
			for(int i=0;i<dk;i++){
				//用增量將序列分割,分別進行直接插入排序。隨着增量變小為1,最后整體進行直接插入排序
				for(int j=i+dk;j<a.length;j = j+dk){
					k = j-dk;
					sentinel = a[j];
					while(k>=0 && sentinel<a[k]){
						a[k+dk] = a[k];
						k = k-dk;
					}
					a[k+dk] = sentinel;
				}
			}
			//當dk為1的時候,整體進行直接插入排序  
			if(dk==1){
				break;
			}
		}
	}

 

五、算法分析

希爾排序的算法性能

排序類別

排序方法

時間復雜度

空間復雜度

穩定性

復雜性

平均情況

最壞情況

最好情況

插入排序

希爾排序

O(Nlog2N)

O(N1.5)

 

O(1)

不穩定

較復雜

時間復雜度

步長的選擇是希爾排序的重要部分。只要最終步長為1任何步長序列都可以工作。

算法最開始以一定的步長進行排序。然后會繼續以一定步長進行排序,最終算法以步長為1進行排序。當步長為1時,算法變為插入排序,這就保證了數據一定會被排序。
Donald Shell 最初建議步長選擇為N/2並且對步長取半直到步長達到1。雖然這樣取可以比O(N2)類的算法(插入排序)更好,但這樣仍然有減少平均時間和最差時間的余地。可能希爾排序最重要的地方在於當用較小步長排序后,以前用的較大步長仍然是有序的。比如,如果一個數列以步長5進行了排序然后再以步長3進行排序,那么該數列不僅是以步長3有序,而且是以步長5有序。如果不是這樣,那么算法在迭代過程中會打亂以前的順序,那就

不會以如此短的時間完成排序了。

已知的最好步長序列是由Sedgewick提出的(1, 5, 19, 41, 109,...),該序列的項來自這兩個算式。

這項研究也表明“比較在希爾排序中是最主要的操作,而不是交換。”用這樣步長序列的希爾排序比插入排序和堆排序都要快,甚至在小數組中比快速排序還快,但是在涉及大量數據時希爾排序還是比快速排序慢。

 算法穩定性

由上文的希爾排序算法演示圖即可知,希爾排序中相等數據可能會交換位置,所以希爾排序是不穩定的算法。

六、問題

希爾排序一定正確么?換句話說如何選取增量序列才能保證正確(包括長度、值)?是的,最后一次只要保證增量是1就ok(不管序列長度,只不過效率就低了),若是序列只有1,那就是直接插入排序了,不知道對否。

七、下面給大家列出8種排序之間的關系:

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM