【问题标题】:What algorithm meets the complexity requirements of the C++ `std::stable_sort`?什么算法满足 C++ `std::stable_sort` 的复杂度要求?
【发布时间】:2021-12-08 00:24:34
【问题描述】:

www.cppreference.com 的文档说std::stable_sort() 的复杂性是

O(n * log(n)^2) [...]。如果有额外的内存可用,那么复杂度是 O(n * log(n))。

什么算法可以满足这个要求,指定的“额外内存”是多少?

【问题讨论】:

  • “什么实现满足这个要求?”嗯,任何符合标准的实现。例如,libstdc++libc++。对于额外内存的大小,我想这取决于实现来定义它需要什么。您可以查看任何实现(例如 libstdc++)并查看它们需要多少以及在哪种情况下。
  • 什么实现?任何合规。我猜大多数实现都使用某种形式的合并排序(或其变体),这需要一个额外的大小为 n. 的“数组”
  • 由于任何符合要求的实现都符合定义,您是否想知道是否有任何实现使用额外的内存来降低复杂性?
  • @molbdnilo 我想知道什么样的算法(或上面提到的合并排序形式)会有这种复杂性,为什么它依赖于可用内存。
  • 一般是归并排序。 inplace_merge 有一个众所周知的线性时间 + 线性空间实现,还有一个众所周知的对数线性时间 + 对数空间实现,标准要求至少有那么好

标签: c++ algorithm sorting std c++-standard-library


【解决方案1】:

根据问题的评论者和一些进一步的阅读,复杂性是这样指定的,因为没有简单的稳定就地 O(nlogn) 排序算法。通过对源代码的进一步检查,libc++libstdc++ 的实现是相似的,都是合并排序,其中就地合并的复杂度为 O(nlogn)。至于“额外内存”,这两个库都需要N个额外内存,其中N是数组的长度。

更具体地说,代替线性扫描两个子数组并一次合并一个元素,就地合并搜索将两个子数组中的每一个分成两部分(总共四部分),例如交换中间两部分时,最左边两部分中的所有元素都小于或等于最右边两部分。然后分别对最左边和最右边两部分进行就地合并。

【讨论】:

    猜你喜欢
    • 2014-02-21
    • 2013-01-10
    • 1970-01-01
    • 2014-07-22
    • 1970-01-01
    • 1970-01-01
    • 2014-08-20
    • 2020-09-14
    • 1970-01-01
    相关资源
    最近更新 更多