最后我发现三元快速排序效果很好。我在www.larsson.dogma.net/qsufsort.c找到了算法。
这是我修改后的实现,与 std::sort 的接口类似。在我的机器和数据集上,它比 std::sort 快 40%。
#include <iterator>
template<class RandIt> static inline void multiway_qsort(RandIt beg, RandIt end, size_t depth = 0, size_t step_len = 6) {
if(beg + 1 >= end) {
return;
}
struct { /* implement bounded comparing */
inline int operator() (
const typename std::iterator_traits<RandIt>::value_type& a,
const typename std::iterator_traits<RandIt>::value_type& b, size_t depth, size_t step_len) {
for(size_t i = 0; i < step_len; i++) {
if(a[depth + i] == b[depth + i] && a[depth + i] == 0) return 0;
if(a[depth + i] < b[depth + i]) return +1;
if(a[depth + i] > b[depth + i]) return -1;
}
return 0;
}
} bounded_cmp;
RandIt i = beg;
RandIt j = beg + std::distance(beg, end) / 2;
RandIt k = end - 1;
typename std::iterator_traits<RandIt>::value_type key = ( /* median of l,m,r */
bounded_cmp(*i, *j, depth, step_len) > 0 ?
(bounded_cmp(*i, *k, depth, step_len) > 0 ? (bounded_cmp(*j, *k, depth, step_len) > 0 ? *j : *k) : *i) :
(bounded_cmp(*i, *k, depth, step_len) < 0 ? (bounded_cmp(*j, *k, depth, step_len) < 0 ? *j : *k) : *i));
/* 3-way partition */
for(j = i; j <= k; ++j) {
switch(bounded_cmp(*j, key, depth, step_len)) {
case +1: std::iter_swap(i, j); ++i; break;
case -1: std::iter_swap(k, j); --k; --j; break;
}
}
++k;
if(beg + 1 < i) multiway_qsort(beg, i, depth, step_len); /* recursively sort [x > pivot] subset */
if(end + 1 > k) multiway_qsort(k, end, depth, step_len); /* recursively sort [x < pivot] subset */
/* recursively sort [x == pivot] subset with higher depth */
if(i < k && (*i)[depth] != 0) {
multiway_qsort(i, k, depth + step_len, step_len);
}
return;
}