1. 程式人生 > >5. 快速排序

5. 快速排序

nbsp 個數 void 排序 com return swa quic turn

一、基本思想

通過一趟排序將要排序的數據分割成獨立的兩部分,其中一部分的所有數據都比另外一部分的所有數據小,然後再按此方法對這兩部分數據分別進行快速排序,整個排序過程可以遞歸進行,以使整個序列有序。

在分割的過程中,樞紐元的選擇至關重要。原因如下:

  (1)兩部分數據是以樞紐元為分界點,小於等於樞紐元的數全部放在樞紐元的左邊,而大於等於樞紐元的數全部放在樞紐元的右邊;

  (2)一般選用左端、右端和中心位置上的三個元素的中值作為樞紐元,即三數取中法,它可以很大程度上避免分組“一邊倒”的情況。

二、三數取中

在快排的過程中,每一趟排序我們都要取一個元素作為樞紐值,以這個數字來將序列劃分為兩部分。

在此我們采用三數取中法,也就是取左端、中間、右端三個數,然後進行排序,將中間數作為樞紐值。

技術分享圖片

三、根據樞紐值進行分割

技術分享圖片

四、代碼

/* 快速排序 */ 
void QuickSort(int a[], int left, int right)
{
	if(left >= right)
		return;
	
	// 采用三數取中法,獲取樞紐元,並將其放在當前待處理序列末尾 
	DealPivot(a, left, right);
	int pivot = a[right-1];			// pivot為樞紐元,而其下標為right-1 

	int i = left, j = right - 1;	// 設置兩個遊標,用以標記待排序區間
	// 當 i = j 時,已經查找完整個區間了 
	while(i != j) {
		while(i < j && a[i] <= pivot) 	// 因為樞紐元在右邊,所以從左邊開始 
			++i;
		while(i < j && a[j] >= pivot)
			--j;
		if(i < j)
			swap(a[i], a[j]);
	}
	// 此時 i = j 
	swap(a[i], a[right-1]);	
		
	sort(a, left, i-1);
	sort(a, i+1, right);
}

// 處理樞紐元 
void DealPivot(int a[], int left, int right)
{
	int mid = (left + right) / 2;
	if(a[left] > a[mid])
		swap(a[left], a[mid]);
	if(a[left] > a[right])	
		swap(a[left], a[right]);
	if(a[mid] > a[right])
		swap(a[mid], a[right]);
	swap(a[mid], a[right-1]);		// 將樞紐元放到倒數第二個元素去,所以要先從左邊檢索 
}

  

5. 快速排序