插入排序

</pre><pre name="code" class="html">

對於插入排序,我們將其僞代碼過程命名爲INSERTION-SORT,其中的參數是一個數組A[1..n],包含長度爲n的要排序的一個序列。(在代碼中,A中元素的數目n用A.length來表示。)該算法原址排序輸入的數:算法在數組A中重排這些數,在任何時候,最多隻有其中的常數個數字存儲在數組外面。在過程INSERTION-SORT結束時,輸入數組A包含排序好的輸出序列。
INSERTION-SORT(A)
1 for j = 2 to A.length
2  key = A[j]
3  // Insert A[j] into the sorted sequence A[1..j - 1].
4  i = j - 1
5  while i > 0 and A[i] > key
6    A[i+1] = A[i]
7    i = i - 1
8  A[i + 1] = key

循環不變式與插入排序的正確性


 

圖2-2表明對A=〈5,2,4,6,1,3〉該算法如何工作。下標j指出正被插入到手中的“當前牌”。在for循環(循環變量爲j)的每次迭代的開始,包含元素A[1..j-1]的子數組構成了當前排序好的左手中的牌,剩餘的子數組A[j+1..n]對應於仍在桌子上的牌堆。事實上,元素A[1..j-1]就是原來在位置1到j-1的元素,但現在已按序排列。我們把A[1..j-1]的這些性質形式地表示爲一個循環不變式:

在第1~8行的for循環的每次迭代開始時,子數組A[1..j-1]由原來在A[1..j-1]中的元素組成,但已按序排列。

圖2-2 在數組A=〈5,2,4,6,1,3〉上INSERTION-SORT的操作。數組下標出現在長方形的上方,數組位置中存儲的值出現在長方形中。(a)~(e)第1~8行for循環的迭代。每次迭代中,黑色的長方形保存取自A[j]的關鍵字,在第5行的測試中將它與其左邊的加陰影的長方形中的值進行比較。加陰影的箭頭指出數組值在第6行向右移動一個位置,黑色的箭頭指出在第8行關鍵字被移到的地方。(f)最終排序好的數組

/**
	 * 插入排序
	 * 對指定數組進行排序
	 * @param a  要排序的數組
	 * @return  返回排序好的數組
	 */
	public static int[] insertSort(int[] a){
		for(int j=1;j<a.length;j++){
			int key = a[j];
			int i = j-1;
			while(i>=0&&a[i]>key){
				a[i+1] = a[i];   //將大的向後推移一個
				i = i-1;
			}
			a[i+1] = key;  //插入將要插入的數
		}
		return a;
	}



循環不變式主要用來幫助我們理解算法的正確性。關於循環不變式,我們必須證明三條性質:

初始化:循環的第一次迭代之前,它爲真。

保持:如果循環的某次迭代之前它爲真,那麼下次迭代之前它仍爲真。

終止:在循環終止時,不變式爲我們提供一個有用的性質,該性質有助於證明算法是正確的。

當前兩條性質成立時,在循環的每次迭代之前循環不變式爲真。(當然,爲了證明循環不變式在每次迭代之前保持爲真,我們完全可以使用不同於循環不變式本身的其他已證實的事實。)注意,這類似於數學歸納法,其中爲了證明某條性質成立,需要證明一個基本情況和一個歸納步。這裏,證明第一次迭代之前不變式成立對應於基本情況,證明從一次迭代到下一次迭代不變式成立對應于歸納步。

第三條性質也許是最重要的,因爲我們將使用循環不變式來證明正確性。通常,我們和導致循環終止的條件一起使用循環不變式。終止性不同於我們通常使用數學歸納法的做法,在歸納法中,歸納步是無限地使用的,這裏當循環終止時,停止“歸納”。

讓我們看看對於插入排序,如何證明這些性質成立。

初始化:首先證明在第一次循環迭代之前(當j=2時),循環不變式成立。所以子數組A[1..j-1]僅由單個元素A[1]組成,實際上就是A[1]中原來的元素。而且該子數組是排序好的(當然很平凡)。這表明第一次循環迭代之前循環不變式成立。

保持:其次處理第二條性質:證明每次迭代保持循環不變式。非形式化地,for循環體的第4~7行將A[j-1]、A[j-2]、A[j-3]等向右移動一個位置,直到找到A[j]的適當位置,第8行將A[j]的值插入該位置。這時子數組A[1..j]由原來在A[1..j]中的元素組成,但已按序排列。那麼對for循環的下一次迭代增加j將保持循環不變式。

第二條性質的一種更形式化的處理要求我們對第5~7行的while循環給出並證明一個循環不變式。然而,這裏我們不願陷入形式主義的困境,而是依賴以上非形式化的分析來證明第二條性質對外層循環成立。

終止:最後研究在循環終止時發生了什麼。導致for循環終止的條件是j>A.length=n。因爲每次循環迭代j增加1,那麼必有j=n+1。在循環不變式的表述中將j用n+1代替,我們有:子數組A[1..n]由原來在A[1..n]中的元素組成,但已按序排列。注意到,子數組A[1..n]就是整個數組,我們推斷出整個數組已排序。因此算法正確。






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