先看看排序算法的C++代碼實現:
#include <iostream>
#include <vector>
using namespace std;
/*函數原型*/
void sort(std::vector<int> &vec);
void quickSort(std::vector<int> & vec, int start, int finish);
int partition(std::vector<int> & vec, int start, int finish);
/*主函數*/
int main(){
vector<int> vec;
for (int i = 0; i < 8; i++){
int n;
cin >> n;
vec.push_back(n);
}
sort(vec);
for(int k = 0; k < vec.size();k++){
cout << vec[k] <<" ";
}
return 0;
}
/*
*函數: quickSort
*對下標位置之間的元素進行排序,包括開始位置和結束位置。
*Quicksort算法開始於“分割”後向量
*使得小於指定的樞軸元素的所有元素都顯示在邊界的左側,
*並且所有相等或更大的值都顯示在右側。
*將子vector排序到邊界的左側和右側確保整個vector被排序。
*/
void quickSort(vector<int> & vec, int start, int finish) {
if (start >= finish) return; //下標相同,返回
int boundary = partition(vec, start, finish); //找樞紐
quickSort(vec, start, boundary - 1); //對vec的樞紐左邊快速排序排序
quickSort(vec, boundary + 1, finish);//對vec樞紐右邊快速排序
}
/*
*該函數重新排列vector的元素,使得小元素被分組在向量的左端,
*而大元素分組在右端。通過比較每個元素與最初從vec [start]
*獲得的樞紐值來進行小和大的區別。當分區完成時,函數返回一
*個邊界索下標,使得0對於所有i <boundary,vec [i] <pivot,
*對於vec [i] == pivot,i == boundary,對於i > pivot,
*vec [i]> = pivot,
*/
int partition(vector<int> & vec, int start, int finish){
int pivot = vec[start];
int lh = start + 1;
int rh = finish;
while(true){
while(lh < rh && vec[rh] >= pivot) rh--;
while(lh < rh && vec[lh] < pivot) lh++;
if(lh == rh) break;
int temp;
int tmp = vec[lh];
vec[lh] = vec[rh];
vec[rh] = tmp;
}
if (vec[lh] >= pivot) return start;
vec[start] = vec[lh];
vec[lh] = pivot;
return lh;
}
/*
*用wrapper函數將函數調用變得更加簡單*/
void sort(vector<int> &vec){
quickSort(vec, 0, vec.size() - 1);
}
上述代碼在VS2015編譯成功:
性能分析
合併排序和Quicksort算法的實際運行時間的比較如下圖所示。Quicksort的這種實現往往比合並排序的執行速度快幾倍,這就是爲什麼程序員在實際中更頻繁地使用它的原因之一。此外,兩種算法的運行時間似乎都以大致相同的方式增長。
但是僅僅比較上圖,卻忽略了一點,只要Quicksort算法選擇一個接近於向量中值的樞軸,分區步驟就會將vector劃分成大致相等的部分。如果算法選擇其樞軸值較差,則兩個部分向量中的一個可能比另一個部分向量大得多,這違反了分治策略的原則。當要排序的vector中的數據是隨機的時,Quicksort往往表現很好,平均情況下爲O(N log N)。在最壞的情況下(比如這個vector已經排好了序 )性能退化爲O(N^2)。
不過,儘管在最壞的情況下這種它的表現很差,但是Quicksort在實踐中比大多數其他算法要快得多,目前它已經成爲一般分類過程的標準選擇。
我們可以使用幾種方式來增加樞紐實際上接近vector中值的可能性。一個簡單的方法是讓Quicksort實現隨機選擇pivot元素。雖然隨機過程仍然可能選擇不良的樞軸值,但是在遞歸分解的每個級別都不太可能會發生相同的錯誤。此外,原始vector的分佈總是隨機的,給定任何輸入,隨機選擇樞軸確保該向量的平均情況性能爲O(N log N)。另一種方法是從vector中選擇一些值,通常爲三或五個,並選擇這些值的中位數作爲樞紐。