【问题标题】:What algorithms do popular C++ compilers use for std::sort and std::stable_sort?流行的 C++ 编译器对 std::sort 和 std::stable_sort 使用什么算法?
【发布时间】:2013-01-10 22:49:53
【问题描述】:

流行的 C++ 编译器对 std::sort 和 std::stable_sort 使用什么算法?我知道标准只给出了某些性能要求,但我想知道流行的实现在实践中使用了哪些算法。

如果它引用每个实现的参考,答案会更有用。

【问题讨论】:

  • Introsort 是快速排序、堆排序和插入排序的组合。
  • @phant0m : 你的“重复”没有提到 stable_sort。
  • 嗯,对,我可能有点高兴。对不起。
  • 现在,不要难过 ;) 您随时可以重新打开它。我不认为问题重叠是一个问题,在两个答案中比较这两件事会很方便。如果我是你,我会还原更改。
  • 请投票重新打开,因为这不是重复的,并且链接问题中的答案不回答这个问题。

标签: c++ algorithm sorting compiler-construction computer-science


【解决方案1】:

首先:编译器不提供std::sort任何 实现。虽然传统上每个编译器都预先打包了一个标准库实现(它严重依赖于编译器的内置),但理论上您可以将一个实现换成另一个。一个很好的例子是 Clang 编译 libstdc++(传统上使用 gcc 打包)和 libc++(全新)。

现在已经不碍事了……

std::sort 传统上被实现为intro-sort。从高级的角度来看,这意味着一个相对标准的快速排序实现(通过一些中值探测来避免 O(n2) 最坏情况)加上一个用于小输入的插入排序例程。然而,libc++ 实现略有不同,更接近于 TimSort:它检测输入中已经排序的序列并避免再次对它们进行排序,从而导致完全排序输入的 O(n) 行为。它还为小输入使用优化的sorting networks

另一方面,std::stable_sort 本质上更复杂。这可以从标准的措辞中推断出来:复杂度是 O(n log n) if 可以分配足够的额外内存(提示 merge-sort) ,但如果不是,则退化为 O(n log2 n)。

【讨论】:

  • 我一直在努力寻找O(n lg^2 n) "mergesort" 一段时间。这绝对不是通常的合并排序,因为它不使用额外的内存——它会是什么?
  • @VF1 这可能是合并排序与 O(n log n) 就地合并步骤。
  • @NiklasB。好吧,我得到了这么多,我正在寻找更深入的论文。
  • @VF1 深入的论文将主要是关于线性时间合并,O(n lg n) 合并实际上非常简单,参见例如这里的合并方法:h2database.googlecode.com/svn/trunk/h2/src/tools/org/h2/dev/…
  • 相当老的帖子,但想添加Introsort算法的维基百科URL,其中还包括算法的伪代码en.wikipedia.org/wiki/Introsort
【解决方案2】:

如果我们以 gcc 为例,我们看到它是对 std::sort 的 introsort 和对 std::stable_sort 的合并排序。

如果您浏览libc++ code,您会发现如果范围足够大,它也会对std::stable_sort 使用合并排序。

您还应该注意的一点是,虽然一般方法始终是上述方法之一,但它们都针对各种特殊情况进行了高度优化。

【讨论】:

    猜你喜欢
    • 2014-07-22
    • 2020-09-14
    • 2021-12-08
    • 2014-05-18
    • 2010-10-23
    • 1970-01-01
    • 2021-10-28
    • 2020-11-03
    • 1970-01-01
    相关资源
    最近更新 更多