c++ - std::sort 是对整数值有限的巨大数组进行就地排序的最佳选择吗?

标签 c++ sorting

我想对一个包含大量(数百万甚至数十亿)元素的数组进行排序,而值是小范围内的整数(1 到 100 或 1 到 1000),在这种情况下,是 std::sort 和并行化版本 __gnu_parallel::sort 是我的最佳选择?

实际上我想用一个代表处理器索引的整数成员对我自己的类的 vector 进行排序。

由于类中还有其他成员,因此,即使两个数据具有相同的用于比较的整数成员,也可能不会将它们视为相同的数据。

最佳答案

如果您知道您的范围如此有限,那么计数排序将是正确的选择。如果范围是 [0,m) 最有效的方法是它有一个 vector,其中索引代表元素,值代表计数。例如:

vector<int> to_sort;
vector<int> counts;
for (int i : to_sort) {
  if (counts.size() < i) {
    counts.resize(i+1, 0);
  }
  counts[i]++;
}

请注意,i 处的计数是延迟初始化的,但如果您知道 m,则可以调整一次大小。

如果您按某个字段对对象进行排序并且它们都是不同的,则可以将上面的内容修改为:

vector<T> to_sort;
vector<vector<const T*>> count_sorted;
for (const T& t : to_sort) {
  const int i = t.sort_field()
  if (count_sorted.size() < i) {
    count_sorted.resize(i+1, {});
  }
  count_sorted[i].push_back(&t);
}

现在的主要区别在于您的空间需求大幅增长,因为您需要存储指针 vector 。空间复杂度从 O(m) 变为 O(n)。时间复杂度是一样的。请注意,该算法是稳定的。上面的代码假定 to_sortcount_sorted 的生命周期内处于范围内。如果您的 T 实现了移动语义,您可以存储对象本身并将它们移入。如果您需要 count_sortedto_sort 更有效,您将需要这样做或复制。

如果你有一个 [-l, m) 类型的范围,内容不会有太大变化,但你的索引现在代表值 i + l 而你需要事先知道l

最后,通过迭代 counts 数组并考虑计数值来模拟排序数组的迭代应该是微不足道的。如果您想要 STL 之类的迭代器,您可能需要一个封装该行为的自定义数据结构。

注意:在此回答的前一个版本中,我提到了 multiset 作为一种使用数据结构进行计数排序的方法。这在一些 java 实现中是有效的(我相信 Guava 实现是有效的)但在 C++ 中不是,因为 RB 树中的键只是重复了很多次。

关于c++ - std::sort 是对整数值有限的巨大数组进行就地排序的最佳选择吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30547452/

相关文章:

arrays - 如何使用 sorted 对元组数组进行排序? (无法使用类型参数列表调用 'sorted')

c++ - 如何对结构C++的 vector 进行排序

Java - 如何在列表开头移动特定整数?

c++ - Qt toDouble() 方法转换为 int

clearcase - 静态分析工具的使用——使用 Clear Case/Quest

c++ - 不使用正则表达式解析 HTTP 请求

c++ - 运算符优先级在 C++ 中不符合预期

c++ - 正则表达式和无效的空指针表达式

mongodb - 在 spring-data mongodb 中对数组进行排序

c++ - C++/STL 中是否支持按属性对对象进行排序?