快速排序是一種最壞情況已耗用時間為O(n*n),雖然這個最壞情況已耗用時間比較差,但快速排序通常都是用於排序的最
佳的實用選擇,這是因為其平均效能相當好:期望的已耗用時間為O(nlgn),且O(nlgn)記號中隱含的常數因子很小。另
外,它還能夠進行就地排序。
快速排序和合并排序一樣,採用的都是分治思想。快排中利用該思想解決步驟為:
1、先從數組中取出一個數作為基數,基數的選擇對排序效率的影響很大
2、分區,將比這個基數小的數全部放到它的左邊,比基數大的數全部放到其右邊
3、對左右兩個區間重複第二步,直到每個區間只有一個數
下面結合代碼來進一步理解快速排序。演算法導論上一開始給出的基數選擇就是直接選擇待排序數組中最後一個元素作
為基數,即對於數組a[N],以a[N-1]作為基數。以一般情況來討論,當我們要進行排序的數組為a[p...r]時,選擇a[r]為
基數,然後將這個序列分為3部分,a[p...q-1],a[q], a[q+1, r],其中a[p...q-1]的元素都是小於基數的,a[q]就是基
數,a[q+1, r]的元素都大於基數。其實現代碼如下:
int partition (int a[], int p, int r){int i = p - 1;for (int j = p; j < r; j++){if (a[j] < a[r]){swap (a[++i], a[j]);}}swap (a[++i], a[r]);return i;}
該函數的執行過程如:
這個函數最後返回的便是q,接下來我們便要對a[p...q-1]和a[q+1, r]重複上述步驟,直到只剩下一個元素。代碼如下:
void quick_sort (int a[], int p, int r){if (p < r){int q = partition (a, p, r);quick_sort (a, p, q - 1);quick_sort (a, q + 1, r);}}
最後附上我自己的一個完整的代碼,可以直接運行測試回合結果:
#include<iostream>using namespace std;void display (int a[], int n);void swap (int& n, int& m);int partition (int a[], int p, int r);void quick_sort (int a[], int p, int r);int main(){int a[100];int n;while (cin >> n){for (int i = 0; i < n; i++)cin >> a[i];quick_sort (a, 0, n - 1);display (a, n);}return 0;}void display (int a[], int n){for (int i = 0; i < n; i++)cout << a[i] << " ";cout << endl;}void swap (int& n, int& m){int temp;temp = n;n = m;m = temp;}int partition (int a[], int p, int r){int i = p - 1;for (int j = p; j < r; j++){if (a[j] < a[r]){swap (a[++i], a[j]);}}swap (a[++i], a[r]);return i;}void quick_sort (int a[], int p, int r){if (p < r){int q = partition (a, p, r);quick_sort (a, p, q - 1);quick_sort (a, q + 1, r);}}
演算法導論書上在最後還提供了幾個改進的版本,如隨機化版本,三數取中等,這些改進的版本基本都是在對基數選擇
方法上進行改進的。有興趣的朋友可以自己試試!