QuickSort 快速排序的分析與實現



/*
  快速排序(QuickSort)


  2013年10月3日
  by --- acton
  算法思想 
         快速排序是C.R.A.Hoare於1962年提出的一種劃分交換排序。它採用了一種分治的策略,通常稱其爲分治法(Divide-and-ConquerMethod)。
(1)   分治法的基本思想 
         分治法的基本思想是:將原問題分解爲若干個規模更小但結構與原問題相似的子問題。遞歸地解這些子問題,然後將這些子問題的解組合爲原問題的解。
(2)快速排序的基本思想 
         設當前待排序的無序區爲R[low..high],利用分治法可將快速排序的基本思想描述爲: 
①分解:   
         在R[low..high]中任選一個記錄作爲基準(Pivot),以此基準將當前無序區劃分爲左、右兩個較小的子區間R[low..pivotpos-1)和R[pivotpos+1..high],並使左邊子區間中所有記錄的關鍵字均小於等於基準記錄(不妨記爲pivot)的關鍵字pivot.key,右邊的子區間中所有記錄的關鍵字均大於等於pivot.key,而基準記錄pivot則位於正確的位置(pivotpos)上,它無須參加後續的排序。 
    注意: 
         劃分的關鍵是要求出基準記錄所在的位置pivotpos。劃分的結果可以簡單地表示爲(注意pivot=R[pivotpos]): 
         R[low..pivotpos-1].keys≤R[pivotpos].key≤R[pivotpos+1..high].keys 
                                    其中low≤pivotpos≤high。 
②求解:   
          通過遞歸調用快速排序對左、右子區間R[low..pivotpos-1]和R[pivotpos+1..high]快速排序。 
③組合:   
         因爲當 "求解 "步驟中的兩個遞歸調用結束時,其左、右兩個子區間已有序。對快速排序而言, "組合 "步驟無須做什麼,可看作是空操作。

  快速排序的複雜度是O(nlgn),其遞歸樹的表示形式應該爲T(n) = 2T(n/2) + O(n) 
  (比較理想的情況是剛好一分爲2,然後問題的規模變小),但是也不排除會出現 T(n) = T(n-1) + O(n)也就是一邊
  有n-1個元素一邊的這種情況,此時的複雜度達到了O(n2)了,蛻化跟InsertSort一樣,所以關鍵是那個劃分的元素的選取,
  如果沒有選取一個比較恰當的pivotkey的話,可能會造成O(n2)的複雜度,但是快速排序在大多的情況下表現的還是比較的優秀的,
  例如當劃分爲一邊爲1/10,另一邊爲9/10, 即爲  T(n) = T((1/10)*n)  + T((9/10)*n)  + O(n)的情況時候,解遞歸樹採用漸進的方法

  可以得到其複雜度近似爲O(nlgn),(見算法導論中文版 P151),所以快速排序還是比較優秀的一個排序的算法,而且它是在對元素進行原地的排序,



  快速排序的隨機化版本:


  如上已經說過,快速排序的key在於partition,而partition的關鍵在於對pivotkey的選取,如果沒有適當的選取,可能會到最壞的複雜度,
  所以此處採用隨機化選取那個pivotkey
  如下僞算法的實現:


  Randomized_Partition(A,p,r){
i = RANDOM(p,r);
Exchange(A[i],A[r]);


  return Partition(A,p,r);
  }
  其他的算法都基本沒有改變主要是pivotkey的選取,算法導論中P157中用指示器隨機 變量證明了該算法的平均複雜度爲O(nlgn)


*/

# include <stdio.h>
# define N  10


void Exchange(int * p, int * q){
	int temp = *p;
	*p = *q ;
	*q = temp;
}


int Partition(int A[], int p , int r){
	int pivot = A[r];				//pivot 應該是隨機選取的
	int i = p -1 ;
	
	for (int j = p ; j < r ; j ++){
		if(A[j] <= pivot){
			i ++ ;
			Exchange(&A[i],&A[j]);
		}
	}
	Exchange(&A[i+1],&A[r]);


	return i + 1 ;
}


void QuickSort(int A[] ,int p ,int r){
	if (p < r){
		int q = Partition(A,p,r);
		QuickSort(A,p,q-1);
		QuickSort(A,q+1,r);
	}
}


int main(void){


	int a [N] = {9,2,10,11,2,8,7,4,3};
	QuickSort(a,3,8);


	for (int i = 3 ; i < 9 ; i ++ ){
		printf("%5d ",a[i]);
	}


	return 0;
}


發佈了14 篇原創文章 · 獲贊 3 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章