分治算法----快速排序

一.算法思想:

假設要對某數組進行由小->大排序

(1) 分解: 對於亂序數組a[R](存取範圍[0->R],有R+1個數),取一個基準元素a[P](一般以第一個數即a[0]爲基準),確定某個Partition(位置)Q ,使a[Q]右邊的數都大於等於a[P],a[Q]左邊的數都小於等於a[P].

(2)遞歸分治:分解之後,數組變成3部分 a[0]-a[Q],a[Q],a[Q+1]-a[R]. a[Q]只有一個元素,以它爲標杆,對a[0]->a[Q]和a[Q+1]->a[R]分別執行步驟(1)

二.例子示例:

數    組: 0  1  2 3 4 5 6

原序列: 7 12 9 8 5 2 3

⑴.令P=0,取標杆a[P]爲7作爲基準,把a[0]存起來,記x=a[0];

令i=P+1,i開始向右邊走,找到>=7的數,此時i停留在下標1處

令j=R,j開始向左移動,找到<=7的數,則j停留在下標6處,如果i<j,交換a[i],a[j];

數    組: 0 1 2 3 4 5 6

現序列: 7 3 9 8 5 212

繼續執行步驟⑴,i到下標2處,j到下標5處,如果i<j,交換a[i],a[j]

數    組: 0 1 2 3 4 5 6
現序列: 7 3 2 8 5 9 12

繼續執行步驟⑴,i到下標3處,j到下標4處,如果i<j,交換a[i],a[j]

數    組: 0 1 2 3 4 5 6

現序列: 7 3 2 5 8 9 12

其中,i,j的移動在循環中(見後續代碼),如果找不到符合條件的數,會一直移動,直到i=r,則數組遍歷完畢,i不再移動,此時i到了下標6處

而j繼續移動,5符合條件,來到下標3處 ,但由於i>=j條件不成立,不交換a[i],a[j],此時交換a[P],a[j],j=3

數    組: 0 1 2 3 4 5 6

現序列: 5 3 2 7 8 9 12

到此一個小分割就結束了,返回j下標Q=3,可以看出a[0->(j-1)]都小於或等於標杆x,即7,a[j+1->R]都大於或等於x.

後續可按上續步驟執行,

a[0]-a[Q]:

數    組: 0 1 2    

現序列: 5 3 2

x=0,i向右走,i=1,直到i=2,j向左找,找到a[j]<=x停止,此時j在下標2處,但由於i<j條件不成立,不交換a[i],a[j],此時交換a[P],a[j],則

數    組: 0 1 2    

現序列: 2 3 5

a[Q+1]-a[R]:

數    組: 3 4 5 6

現序列: 7 8 9 12

同理,由於一直不滿足條件,i走到下標6處 j走到下標3處,此時i>j,執行交換a[P],a[j],原序列不變,算法結束

所以最終序列爲:

數    組: 0 1 2 3 4 5 6

現序列: 2 3 5 7 8 9 12

三.源代碼:

#include<iostream>
using namespace std;
int Partition(int a[],int P, int R);
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 Partition(int a[], int P, int R)
{
	int i=P,j=R+1;//由於i,j先移動 提前加一位,但是以a[0]爲標杆,a[0]不參與比較,i不用先減1,可見★代碼處
	int x=a[P];
	while(true){
		while(a[++i]<x&&i<R);	//★  ++在前,先移動i再比較,所以初始i=P 此處目的是把i移動到a[i]>=x處或者i到最後一位停止.
		while(a[--j]>x);		//把i移動到a[i]<=x處
		if(i>=j) break;			//當i>=j大小標杆劃分完成
		swap(a[i],a[j]);	
	}
	swap(a[P],a[j]);			
	return j;					//返回分界標杆
}

void main()
{
	int a[7]= {7,12,9,8,5,2,3};
	cout<<"原序列:\n";
	for (int i = 0; i < 7; i++)
	{
		cout<<a[i]<<" ";
	}
	Quicksort(a,0,6);		//此處傳第三個參注意爲n-1,n爲待排序數個數,因爲下標從0開始
	cout<<"\n現序列:\n";
	for (int i = 0; i < 7; i++)
	{
		cout<<a[i]<<" ";
	}
}


四.運行結果:



參考資料:《計算機算法設計與分析》 p25

五.時間複雜度:

快速排序每次將待排序數組分爲兩個部分,如果理想,每一次都將待排序數組劃分成等長兩個部分,則需要logn次劃分。
平均需要(nlogn)

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