基数排序,也不需要值小于 m 的限制。
下面的示例实现是在 int 类型上模板化的。如果您的 m 始终小于 2^15,则应尽可能使用 int16_t 向量(如果值始终为正,则应使用更好的 uint16_t 以避免处理有符号整数的偏移量)。对于 32 位整数,这将只需要两次排序,而不是 4 次。如果您无法更改输入类型,则可以将代码特殊情况下仅执行两次传递并避免带符号的偏移量。
这个实现是 O(n) 并且使用了 O(n) 额外空间(排序不到位)。
template<typename I>
void radix_sort(I first, I last) {
using namespace std;
typedef remove_reference_t<decltype(*first)> int_t;
typedef make_unsigned<int_t>::type uint_t;
const uint_t signedOffset = is_signed<int_t>::value ? uint_t(numeric_limits<int_t>::max()) + uint_t(1) : 0;
auto getDigit = [=](uint_t n, int power) -> size_t { return ((n + signedOffset) >> (power * 8)) & 0xff; };
array<size_t, 256> counts;
vector<int_t> sorted(distance(first, last));
for (int power = 0; power < sizeof(int_t); ++power) {
counts.fill(0);
for_each(first, last, [&](int_t i) { ++counts[getDigit(i, power)]; });
partial_sum(begin(counts), end(counts), begin(counts));
for_each(reverse_iterator<I>(last), reverse_iterator<I>(first), [&](int_t i) {
sorted[--counts[getDigit(i, power)]] = i;
});
copy(begin(sorted), end(sorted), first);
}
}