快速(quick)排序算法

快速排序是不穩定的排序。

1、快速排序的基本思想

快速排序是C.R.A.Hoare於1962年提出的一種劃分交換排序。它採用了一種分治的策略,通常撐起爲分治法。分治法的基本思想是:將原問題分解爲若規模更小但結構與原問題相似的子問題。遞歸地解決這些子問題,然後將這些子問題的解組合爲原問題的解。

快速排序的基本思想:設當前的待排序的無序區爲A[low..high],利用分治可描述爲:

(1) 分解:

在A[low...high]中任選一個記錄作爲基準(pivot也叫中軸或者樞紐),依此基準將當前無序區劃分爲左、右兩個較小的自取件A[low...pivot[pos-1]]和A[pivot[pos+1]...high]

並使左邊子區間中所有記錄的關鍵字均小於基準記錄(pivot),右邊的子區間中所有記錄的關鍵字均大於等於pivot,而基準的記錄pivot則位於正確的位置上,它無需在參加後續的排序。注意,劃分的關鍵是要求出基準記錄所在的位置pivot[pos]。劃分的結果可以簡單的表示爲:A[low...pivot[pos-1]]<=A[pivot[pos]]<=A[pivot[pos+1]...high],其中low<=pivot[pos]<=high。

(2) 求解:

通過遞歸調用快速排序對左右子區間A[low...pivot[pos-1]]和A[pivot[pos-1]+1...high]排序。

(3) 組合:

當“求解”步驟中的兩個遞歸調用結束時,子左右兩個子區間已有序。對排序排序而言,“組合”步驟無需做什麼,可以看做空操作。

2、思想

它是由冒泡排序改進而來的。在待排序的n個記錄中任取一個記錄(通常取第一個記錄),把該記錄放入適當位置後,數據序列被此記錄劃分成兩部分。所有關鍵字比該記錄關鍵字小的記錄放置在前一部分,所有比它大的記錄放置在後一部分,並把該記錄排在這兩部分的中間(稱爲該記錄歸位),這個過程稱作一趟快速排序。

說明:最核心的思想是將小的部分放在左邊,大的部分放到右邊,實現分割。

3、算法複雜度

最好的情況下:因爲每次都將序列分爲兩個部分(一般二分都複雜度都和logN相關),故爲 O(N*logN)

最壞的情況下:基本有序時,退化爲冒泡排序,幾乎要比較N*N次,故爲O(N*N)

4、穩定性

由於每次都需要和中軸元素交換,因此原來的順序就可能被打亂。如序列爲 5 3 3 4 3 8 9 10 11會將3的順序打亂。所以說,快速排序是不穩定的!

5、代碼實現

<pre name="code" class="cpp">//編程實現快速排序
//1.快速排序是比較複雜的排序,其中需要知道數組的下標,低位下標要是大於高位下標的話,不進行排序
//2.其中每次取第一個數當做分割點pivot=a[low],循環到低位下標大於高位下標終止循環,這樣就確定了pivot的位置。
//3.遍歷pivot右邊的元素(a[j]>=pivot),若小於pivot將元素放到pivot的左邊(a[i++]=a[j]),第一次放的位置爲low.
//4.之後遍歷low右側的元素,若大於pivot將元素放到pivot的右邊(a[j--]=a[i]),第一次放的位置爲high.
//5.3、4步的大前提是低位下標小於高位下標.
//6.終止循環之後,將pivot放到中間位置(a[i]=pivot).
//7.再將low到i-1,也就是pivot的左側進行同樣排序,i+1到high,pivot的右側進行同樣排序。

#include<iostream>
using namespace std;

void quick_sort(int a[], int low, int high)		//low和high均爲數組的下標
{
	//因爲在遞歸的時候需要low和high的位置,所以需要拷貝low和high
	int i;	//第一個元素下標
	int j;	//最後一個元素下標
	int pivot;   //pivot是區間的第一個元素,也是快速排序的樞紐(以他爲中間元素,在他的左邊元素都是小於他的,右邊的元素都是大於他的)
	if (low < high)		//遞歸的終止條件是,區間完全重合
	{
		pivot = a[low];
		i = low;
		j = high;
		while (i < j)		//找到中間位置(快速排序的終止條件)
		{
			while (i < j && a[j] >= pivot)		//篩選比pivot小的元素
				j--;
			if (i < j)				//中間位置大前提
				a[i++] = a[j];			//將比pivot小的元素賦給區間的第一個元素

			while (i < j && a[i] <= pivot)		//篩選比pivot大的元素
				i++;
			if (i < j)				//中間位置大前提
				a[j--] = a[i];			//將比pivot大的元素賦給比pivot小的元素位置
		}
		a[i] = pivot;					//pivot移到最終位置,樞紐中間位置
		quick_sort(a, low, i - 1);			//對左側遞歸排序
		quick_sort(a, i + 1, high);			//對右側遞歸排序
	}
}

static void print_sort(int a[], int len)
{
	for (int i = 0; i < len; i++)			<span style="white-space:pre">	</span>//打印數組
		cout << a[i] << " ";
}
void main9mianshiti4()
{
	int a[] = { 83, 38, 96, 23, 15, 72, 60, 45, 54 };
	cout << "before quick sort:";
	print_sort(a, 9);					//打印數組
	quick_sort(a, 0, 8);					//快速排序
	cout << "\nafter quick sort:";
	print_sort(a, 9);
	system("pause");
}



6、測試結果

before quick sort:83 38 96 23 15 72 60 45 54

after quick sort:15 23 38 45 54 60 72 83 96

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