什么算法满足C++“std::stable_sort”的复杂度要求?

What algorithm meets the complexity requirements of the C++ `std::stable_sort`?

提问人:Donny Chan 提问时间:10/21/2021 最后编辑:Donny Chan 更新时间:10/23/2021 访问量:108

问:

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

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

什么算法可以满足这一要求,指定的“附加内存”是多少?

C++ 算法 排序 std c++-standard-library

评论

0赞 Fareanor 10/21/2021
“什么实现符合这个要求?”好吧,任何符合标准的实现。例如,libstdc++、libc++对于额外内存的大小,好吧,我想这取决于实现来定义它需要什么。您可以查看任何实现(例如 libstdc++),看看它们需要多少以及在这种情况下。
0赞 Daniel Langr 10/21/2021
什么实现?任何合规。我猜大多数实现都使用某种形式的合并排序(或其变体),这需要一个大小为 n 的额外“数组”。
1赞 molbdnilo 10/21/2021
由于任何符合定义的实现都满足该要求,您是否想知道是否有任何实现使用额外的内存来实现较低的复杂性?
0赞 Donny Chan 10/21/2021
@molbdnilo 我想知道什么样的算法(或上面提到的合并排序形式)会具有这种复杂性,以及为什么它依赖于可用内存。
0赞 Caleth 10/21/2021
通常,它是一种合并排序。inplace_merge有一个众所周知的线性时间+线性空间实现,也有一个众所周知的对数线性时间+对数空间实现,并且该标准至少需要一些好的东西

答:

0赞 Donny Chan 10/23/2021 #1

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

更具体地说,不是线性扫描两个子数组并一次合并一个元素,而是就地合并搜索一种方式将两个子数组中的每一个划分为两个部分(总共四个部分),这样在交换中间两个部分时,最左边两个部分中的所有元素都小于或等于最右边的两个部分。然后,他们分别在最左边和最右边的两个部分执行就地合并。