1. 程式人生 > 實用技巧 >十大排序-快速排序

十大排序-快速排序

快速排序演算法是一種基於交換的高效的排序演算法,它採用了分治法的思想

1.基本實現

1、從數列中取出一個數作為基準數(樞軸,pivot)。

2、將陣列進行劃分(partition),將比基準數大的元素都移至樞軸右邊,將小於等於基準數的元素都移至樞軸左邊。

3、再對左右的子區間重複第二步的劃分操作,直至每個子區間只有一個元素。

快排最重要的一步就是劃分了。劃分的過程用通俗的語言講就是“挖坑”和“填坑”。

2.口訣要領

找基準,做交換,左右繼續。

3.操作注意點(思考原因,寫一寫)

當基準數選擇最左邊的數字時,那麼就應該先從右邊開始搜尋;
當基準數選擇最右邊的數字時,那麼就應該先從左邊開始搜尋。
不論是從小到大排序還是從大到小排序!

4.快速排序時間複雜度

快速排序的時間複雜度在最壞情況下是O(N^2),平均的時間複雜度是O(N*lgN)。

這句話很好理解:假設被排序的數列中有N個數。遍歷一次的時間複雜度是O(N),需要遍歷多少次呢?至少lg(N+1)次,最多N次。

(1) 為什麼最少是lg(N+1)次?快速排序是採用的分治法進行遍歷的,我們將它看作一棵二叉樹,它需要遍歷的次數就是二叉樹的深度,而根據完全二叉樹的定義,它的深度至少是lg(N+1)。

因此,快速排序的遍歷次數最少是lg(N+1)次。

(2) 為什麼最多是N次?這個應該非常簡單,還是將快速排序看作一棵二叉樹,它的深度最大是N。因此,快速排序的遍歷次數最多是N次。


5.快速排序的穩定性

快速排序是不穩定的演算法,它不滿足穩定演算法的定義。 演算法穩定性 -- 假設在數列中存在a[i]-a[j],若在排序之前,a[i]在a[j]前面;並且排序之後,a[i]仍然在a[j]前面。則這個排序演算法是穩定的!
例如,1 3 2 2 4進行快速排序從小到大排序時,3會和第二個2進行交換位置。這樣兩個2的相對位置就改變了。

6.程式碼展示

不用陣列而用vector,是因為函式中陣列的呼叫無法判斷陣列的長度,無法進行判斷是否陣列越界。
#include<iostream>
#include<vector>
using namespace std;

//快速排序(從小到大)
void quickSort(int left, int right, vector<int>& arr)
{
	int length = arr.size();
	if (left >= right || right >= length)
	{
		//cout << "函式初始化錯誤" << endl;
		return;
	}
	int i, j, base, temp;
	i = left, j = right;
	base = arr[left];  //取最左邊的數為基準數
	while (i < j)
	{
		while (arr[j] >= base && i < j)
			j--;
		while (arr[i] <= base && i < j)
			i++;
		if (i < j)
		{
			temp = arr[i];
			arr[i] = arr[j];
			arr[j] = temp;
		}
	}
	//基準數歸位
	arr[left] = arr[i];
	arr[i] = base;
	quickSort(left, i - 1, arr);//遞迴左邊
	quickSort(i + 1, right, arr);//遞迴右邊
}

//快速排序(從大到小)
void quickSort2(int left, int right, vector<int>& arr)
{
	if (left >= right) //遞迴邊界條件
		return;
	if (left < 0 || right >= arr.size())
	{
		cout << "error args! 陣列越界!" << endl;
		return;
	}//非法輸入判斷,防止陣列越界
	int i, j, base, temp;
	i = left, j = right;
	base = arr[left];  //取最左邊的數為基準數
	while (i < j)
	{
		while (arr[j] <= base && i < j)
			j--;
		while (arr[i] >= base && i < j)
			i++;
		if (i < j)
		{
			temp = arr[i];
			arr[i] = arr[j];
			arr[j] = temp;
		}
	}
	//基準數歸位
	arr[left] = arr[i];
	arr[i] = base;
	quickSort2(left, i - 1, arr);//遞迴左邊
	quickSort2(i + 1, right, arr);//遞迴右邊
}


int main() {

	

	vector<int> arr = { 1,3,2,2,4,5,6,0,1 };
	cout << arr.size() << endl;
	quickSort(0, arr.size()-1, arr);
	//quickSort2(0, arr.size()-1, arr);
	for (auto it : arr)
	{
		cout << it;
	}
}

7.引用:

CSDN技術部落格