基准数的选择:采用范围的中间位置的数
编译环境:C++11
代码实现如下:
#include <type_traits> // std::declval
typedef unsigned long size_type;
template<typename _Tp>
constexpr size_type distance(const _Tp &_1, const _Tp &_2)
{ return _1 < _2 ? _2 - _1 : _1 - _2; }
template<typename _Tp>
void swap(_Tp &a1, _Tp &a2)
{
_Tp tmp = a1;
a1 = a2;
a2 = tmp;
}
template<typename _Tp>
struct Comparator
{
int operator()(const _Tp &arg1, const _Tp &arg2) const
{
if(arg1 < arg2) return 1;
if(arg2 < arg1) return -1;
return 0;
}
};
/// 获取范围的基准数
/// 范围:[@beg, @end) 范围,须支持随机迭代
template<typename _RandomIter,
typename _Compare = Comparator<decltype(*std::declval<_RandomIter>())>>
auto median(_RandomIter beg,
_RandomIter end,
_Compare c = _Compare())
-> decltype(*std::declval<_RandomIter>())
{
size_type dist = distance(beg, end);
size_type center = dist / 2;
_RandomIter left = beg, right = beg + dist - 1;
if(c(*(left + center), *left) > 0)
{ swap(*(left + center), *left); }
if(c(*right, *left) > 0)
{ swap(*right, *left); }
if(c(*right, *(left + center)) > 0)
{ swap(*right, *(left + center)); }
swap(*(left + center), *(right - 1));
return *(right - 1);
}
/// 快速排序
/// [@beg, @end) 待排序的范围,同时保存结果,须支持随机迭代
template<typename _RandomIter,
typename _Compare = Comparator<decltype(*std::declval<_RandomIter>())>>
void qsort(_RandomIter beg,
_RandomIter end,
_Compare c = _Compare())
{
size_type right = distance(beg, end) - 1;
size_type i = 0, j = right - 1;
auto pivot(median(beg, end, c));
while(true)
{
while(c(*(beg + (++i)), pivot) > 0);
while(c(pivot, *(beg + (--j))) > 0);
if(i < j)
{ swap(*(beg + i), *(beg + j)); }
else break;
}
swap(*(beg + i), *(beg + right - 1));
qsort(beg, beg + i);
qsort(beg + i + 1, end);
}
如有问题,欢迎指出!