C++一种函数式风格的快速排序

对于快速排序算法,我们可以用以下自然语言来描述其过程:

1.在待排序数组中选择一个哨兵,将其放在正确位置,使得他左边的数都比他小,右边的数都比他大。
2.让哨兵左侧的数组和哨兵右侧的数组也执行同样过程。
3.递归上述过程直至结束。

考虑一下递归的出口,当数组长度小于等于1时,我们认为该数组有序,因此可写出以下代码。

template<typename T>
auto quick_sort(vector<T>& v) {
	if (v.size() < 2) return;//如果长度小于等于1,递归结束
	vector<T> lhs, rhs;
	const T& pivot = v[0];//取数组第一个元素作为哨兵
	copy_if(begin(v) + 1, end(v), back_inserter(lhs), [&](const T& val) { return val <= v[0]; });//将小于等于哨兵的元素塞进lhs
	copy_if(begin(v) + 1, end(v), back_inserter(rhs), [&](const T& val) { return val > v[0]; });//将大于哨兵的元素塞进rhs
	quick_sort(lhs);//递归左侧数组
	quick_sort(rhs);//递归右侧数组
	v[lhs.size()] = pivot;
	copy(begin(lhs), end(lhs), begin(v));
	copy(begin(rhs), end(rhs), begin(v) + lhs.size() + 1);//通过copy将排序完结果赋给原数组v,即v = [lhs] ++ [x] ++ [rhs]
}

嗯,去头去尾只要10行,代码还算简洁,思路清晰,唯一的缺点就是递归过程中不断的copy导致性能比较垃圾,来写一个测试程序简单测测性能。

	vector<int> v1;
	v1.resize(1e7);
	static default_random_engine e(time(nullptr));
	uniform_int_distribution<int> rand;
	generate(v1.begin(), v1.end(), [&] {return rand(e); });
	auto tic = clock();
	quick_sort(v1);
	cout << clock() - tic << "ms" << endl;

测试环境是MSVC、Release、std=C++17,测试结果大致如下

stl sortmy sort
size=1e58ms57ms
size=1e690ms606ms
size=1e71010ms6283ms

在复杂度的常数阶大约差了6倍,还在可接受范围内。
最后附上所有代码

#include<cassert>
#include<vector>
#include<iostream>
#include<algorithm>
#include<random>

using namespace std;

template<typename T>
auto quick_sort(vector<T>& v) {
	if (v.size() < 2) return;
	vector<T> lhs, rhs;
	const T& pivot = v[0];
	copy_if(begin(v) + 1, end(v), back_inserter(lhs), [&](const T& val) { return val <= v[0]; });
	copy_if(begin(v) + 1, end(v), back_inserter(rhs), [&](const T& val) { return val > v[0]; });
	quick_sort(lhs);
	quick_sort(rhs);
	v[lhs.size()] = pivot;
	copy(begin(lhs), end(lhs), begin(v));
	copy(begin(rhs), end(rhs), begin(v) + lhs.size() + 1);
}

int main() {
	vector<int> v1;
	v1.resize(1e7);
	static default_random_engine e(time(nullptr));
	uniform_int_distribution<int> rand;
	generate(v1.begin(), v1.end(), [&] {return rand(e); });
	auto tic = clock();
	quick_sort(v1);
	cout << clock() - tic << "ms" << endl;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值