我正在寻找一种快速稳定的基数排序实现(支持浮点数),它返回排序顺序的索引而不是排序值。
Pierre Terdiman在他的文章“Radix Sort Revisited”中的版本正是我想要的,但是它已经超过 13 年了,不适合现代流水线 CPU。
来自“Radix Tricks”的 Michael Herf 的RadixSort11非常快,唯一的问题是它返回排序后的值而不是索引,此外它还破坏了输入数组的值。
任何帮助,将不胜感激。
我正在寻找一种快速稳定的基数排序实现(支持浮点数),它返回排序顺序的索引而不是排序值。
Pierre Terdiman在他的文章“Radix Sort Revisited”中的版本正是我想要的,但是它已经超过 13 年了,不适合现代流水线 CPU。
来自“Radix Tricks”的 Michael Herf 的RadixSort11非常快,唯一的问题是它返回排序后的值而不是索引,此外它还破坏了输入数组的值。
任何帮助,将不胜感激。
你可以
展开每个项目以包括其原始索引(这可以在第一次计数过程中完成)。当然,出于排序目的,索引数字会被忽略。
将索引存储到存储桶中,而不是值。每次需要数字时查找该值。
第一个占用更多空间但具有更好的参考局部性,第二个节省空间。
基于任何排序索引是相当直接的。任何排序都是一系列比较和交换,所以这样做。
// data to be sorted is in data[ 0 .. n ]
int index[ n + 1 ];
for( int i = 0; i <= n; i++ ) index[i] = i;
// To compare data, compare data[index[j]] < data[index[k]]
// To swap values, swap index[j] <=> index[k]
我不熟悉这些实现,但这是我的一个实现中的内部函数,仅适用于整数:
//-------------------------------------------------------------------------------------
//! sort the source array based on b-th byte and store the result in destination array
//! and keep index (how to go from the sorted array to the un-sorted)
template<typename T, typename SS, typename SD> inline
void radix_sort_byte(size_t b, array<T, SS>& src, array<T, SD>& dest,
size_array& ind_src, size_array& ind_dest)
{
b *= 8;
size_t B = 256, N = src.size();
size_array bytes = (src >> b) & 0xff; // current byte of each element
size_array count(B, size_t(0)); // occurrences of each element
++count[bytes];
if(count[0] == N) // all bytes are zero; order remains unchanged
{ dest = src; ind_dest = ind_src; return; }
size_array index = shift(cumsum(count), 1); // index-list for each element
size_array pos(N); // position of each element in the destination array
for(size_t i=0; i<N; i++) pos[i] = index[bytes[i]]++;
dest[pos] = src; // place elements in the destination array
ind_dest[pos] = ind_src; // place indices
}
它不是直接可读的,因为它使用了许多辅助结构和函数,但想法是您保留一个带有索引的单独数组。一旦你有了目标数组(pos)中元素的位置,最后两行以完全相同的方式更新值数组和索引数组。
我想您可以将相同的想法应用于任何实现,但您必须修改代码。