先看看排序算法的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中选择一些值,通常为三或五个,并选择这些值的中位数作为枢纽。