您的位置:首页 > 其它

如何写出一个较好的快速排序程序

2014-07-27 08:02 477 查看

写出一个较好的快速排序程序

快速排序是常用的排序算法之一,但要想写出一个又快又准的使用程序,就不是那么简单了

需要注意的事项

首先要写正确。通常使用递归实现。其递归相当于二叉树展开,因此如果要用迭代实现的话需要使用一个队列来保存后续遍历信息。
快速排序需要找到一个pivot值,如果顺序选择pivot则易造成N^2的复杂度,如果使用随机数则效果最好,但开销又太大,采取三数中值法比较合适。三数中值法指的是选取第一个值,最后一个值,数组中间的值的中值。有文献表明可以提升5%的运行时间。
当数组长度较小时,如10个元素以下,最好使用插入排序或者选择排序完成,以防止复杂度常数因子过大或多次函数调用带来的开销。而递归到底层数组长度总是会变小的,因此这么做非常有必要。
在合并前后两部分数组时,采用两边夹方法,在前后两部分各找到一个大于和小于的值再交换。相比通常情况下找到比pivot小的值就进行交换,能提高运行效率。

实现代码

代码如下。包括插入排序insert_sort,递归函数,三分中值函数三个辅助函数。
三分中值函数其实采用的是插入排序。通过三次比较,确定中值。
插值算法使用临时变量tmp避免了大量swap函数调用。
#include<iostream>
#include<iomanip>
#include<vector>
#include<cstdlib>
#include<ctime>
#include<algorithm>

using namespace std;

inline void swap(vector<int>& num, int p, int q){
int t = num[p];
num[p] = num[q];
num[q] = t;
}

void insert_sort(vector<int>& num){
int tmp, j;
for (int i = 1; i < num.size(); i++){
tmp = num[i];
for (j = i - 1; j >= 0 && num[j] > tmp; j--)
num[j + 1] = num[j];
num[j + 1] =tmp;
}
}

int quick_sort_sub(vector<int>& num, int p, int q){
if (p >= q)
return 0;

// if 4 elements or less, use insert sort
if (p + 10 > q){
vector<int> tnum(num.begin() + p, num.begin() + q + 1);
insert_sort(tnum);
for (int i = 0; i < tnum.size(); i++)
num[p + i] = tnum[i];
}

int idx = quick_three_partition(num, p, q);
swap(num, idx, q);

int pivot = num[q];
int left = p, right = q - 1;
while (1){
while (num[left] < pivot)
++left;
while (num[right] >= pivot)
--right;
if (left < right)
swap(num, left, right);
else
break;
}
swap(num, left, q);
quick_sort_sub(num, p, left - 1);
quick_sort_sub(num, left + 1, q);

return left;
}

void quick_sort(vector<int>& num){
quick_sort_sub(num, 0, num.size() - 1);
}

int main(){
const int n = 10;
/*int num_array
= {2,1};
vector<int> num(num_array, num_array + n);*/

srand( time(NULL) );
vector<int> num(n);
for (auto& e : num)
e = rand() % n;

quick_sort(num);

for (auto& e : num)
cout << setw(4) << e << ' ';
cout << endl;

cout << "vector is sorted? : " << is_sorted(num.begin(), num.end()) << endl;

return 0;

}


 

 

转载请注明作者:Focustc,博客地址为http://blog.csdn.net/caozhk,原文链接为点击打开
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: