快速排序是不穩定的排序。
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