【发布时间】:2015-05-22 14:56:00
【问题描述】:
StackOverflow 和其他地方有很多声称 nth_element 是 O(n) 并且通常使用 Introselect 实现:http://en.cppreference.com/w/cpp/algorithm/nth_element
我想知道如何实现这一点。我看着Wikipedia's explanation of Introselect,这让我更加困惑。算法如何在 QSort 和 Median-of-Medians 之间切换?
我在这里找到了 Introsort 论文:http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.14.5196&rep=rep1&type=pdf 但上面写着:
在本文中,我们专注于排序问题,并在后面的部分中仅简要介绍选择问题。
我试图通读 STL 本身以了解 nth_element 是如何实现的,但这很快就会变得很麻烦。
有人可以向我展示如何实现 Introselect 的伪代码吗?甚至更好,当然是 STL 以外的实际 C++ 代码:)
【问题讨论】:
-
您是否注意到,根据 cppreference,在平均情况下,算法应该只是
O(n)。它没有说明最坏的情况。这意味着快速选择将是可行的,因为它平均有O(n)。 -
@Nobody cppreference 还指出可以使用除 Introselect 之外的其他东西,这可能不是最坏的情况 O(n)。 Wikipedia 和 Introselect 论文声称 Introselect 在 worst 情况下是 O(n)。
-
正如你所说的 introselect 是快速选择和中位数的组合。快速选择在平均和最佳情况下非常快,但具有二次最坏情况,而中位数的中位数保证是一种较慢的始终线性时间算法。 Introselect 尝试通过 quickselect 来提高速度,如果不能,那么它会退回到较慢但有保证的线性时间算法,从而在它变得比线性更差之前限制其最坏情况的运行时间。也许您应该稍微澄清一下您的问题,因为您的问题似乎有些混乱:STL、Introsort、复杂性?
-
@Nobody 重读我的问题,我明白你在说什么。我有点列出了我不明白的事情的清单。我真正想知道的是 Introsort 是如何工作的。不过,我现在犹豫要不要编辑我的问题,因为它会对以前的答案产生影响。希望仅仅说您的回答解决了我的问题就足够了。但是,如果在阅读完本文后您仍然觉得问题需要编辑,那么您修改它是没有问题的。
-
哦,只是你应该使用另一个字母来表示列表的长度,因为在 nth 元素中已经有一个 n 了。我想每个人都明白你的意思,但最好是准确的,例如。 “列表长度为 m 的第 n 个元素”。文档说算法是 O(m) 这与 O(n) 不同
标签: c++ algorithm stl selection nth-element