最坏情况


35

我很难找到可以给出最坏情况良好资源,而不是稳定排序算法。有人知道任何好的资源吗?O(nlnn)

提醒一下,这意味着它使用传入的数组,并且排序算法仅允许使用恒定的额外空间。稳定意味着具有相同键的元素在排序数组中的顺序与原始数组中的顺序相同。

例如,朴素的合并排序是最坏的情况且稳定,但使用多余的空间。可以使标准的快速排序稳定,到位,但最坏的情况是。堆排序已经到位,最坏的情况是O(n \ ln n),但不稳定。 维基百科上有一张很好的图表,说明了哪种排序算法有哪些弊端。请注意,他们没有列出列出所有具有稳定性的三个条件的排序算法,最坏情况为O(n \ ln n)且处于适当状态。O(nlnn)O(n)O(n2)O(nlnn)O(nlnn)

我发现Katajainen,Pasanen和Teuhola撰写了一篇名为“ Practical in-place mergesort”的论文,该论文声称就地稳定的mergesortsort变种最坏的情况。如果我正确理解了它们的结果,它们将在数组的第一个和数组的后一个上递归使用(bottom-up?)mergesort,然后使用第二个作为合并的临时空间。我仍在阅读此书,因此感谢您提供有关我是否正确解释其结果的更多信息。O(nlnn)141214

我也会对最坏情况进行稳定快速排序感兴趣。据我了解,将快速排序修改为最坏的情况需要选择一个适当的枢轴,这将破坏原本通常会享有的稳定性。O(nlnn)O(nlnn)

这纯粹是理论上的兴趣,我没有实际应用。我只想知道具有所有这三个功能的算法。


关于被如此类似的问题在这里有一个答案,让在这个问题提供的参考我。我认为这不是重复的问题,因为我需要进一步的澄清,更多的文献资料,并且幸运的是,对该算法进行了描述。
user834 2012年

1
请参阅math.stackexchange.com上的此问题
伊藤刚(Tsuyoshi Ito)

为什么在QuickSort中选择支点的不同方法会破坏其稳定性?
svick

@svick,我知道如何使QuickSort最坏情况的唯一方法是比随机选择更智能地选择轴。我学会的方法是使用选择算法,该算法使用中位数算法,这会破坏稳定性。如果我错过了什么,请告诉我。O(nlnn)
user834 2012年

@TsuyoshiIto,考虑将其作为答案。另外,如果您可以简要介绍一下该算法,那么我认为这也会很有帮助。
user834 2012年

Answers:


6

以上都是几种算法,并且在过去30年中几乎所有的算法都被发明了。

也许最好的算法是称为Block sort的算法,其中包括Kim和Kutzner在2008年提出的算法(称为WikiSort)。它不仅稳定而且完全就位(跨二分模型中的O(1)内存开销),而且也是自适应的,因此将需要较少的步骤来对几乎排序的列表进行排序,在已经排序的列表的情况下,收敛到O(n)比较。您可以在这里找到C,C ++和Java的实现:https//github.com/BonzaiThePenguin/WikiSort

同样令人感兴趣的是Huang和Langston(1989-1992)的GrailSort算法(也是Block排序),在几种类型的测试用例上,它的性能实际上优于WikiSort。此处提供了C ++实现:https//github.com/Mrrl/GrailSort


8

您可以编写就地,稳定的mergesort。请参阅了解详情。用作者自己的话说:

美丽到位-合并算法。在反向阵列上对其进行测试,以了解旋转的工作原理。最快已知的稳定排序方式。没有爆炸堆栈的风险。费用:相对较高的招数。堆栈仍然可能很昂贵。这是具有“旋转”子数组的智能就地合并的合并排序。此代码从C ++ stl库中完全复制并用Java翻译。

我不会在这里复制代码,但是您可以在链接中或通过检查C ++ STL来找到它。如果您希望我尝试提供此处发生的情况的详细说明,请告诉我。


8
如果您能做一个简短的描述,我认为这将非常有帮助。此外,尽管可能没有必要,但引用的实现使用的是递归,它在空间上添加了另一个因子,这违反了O 1 空间条件(假设我们免费获得O ln n 位变量) 。也许可以将引用的算法设为迭代算法,但我无法理解正在发生的事情。您是否有实施使用的参考文件?O(lnn)O(1)O(lnn)
user834 2012年

Knuth也在TAoCP中解决了这一问题。
拉斐尔

您在此处引用的算法是最坏的情况。cf. cplusplus.com/reference/algorithm/stable_sort(尤其是在没有足够的额外内存可用时有关运行时间的注释)。O(nln2n)
quintopia

1

请将此作为对一些实际想法的详尽评论。尽管这不是您问题的答案,但我认为您可能对此Python讨论感兴趣:

lg(N!)N1

[...]

就地合并长度为A和B的相邻行非常困难。可以做到的理论构造是众所周知的,但是对于实际使用而言,它们太困难又太慢。但是,如果我们的临时内存等于min(A,B),这很容易。

资料来源:bugs.python.org,作者:Tim Peters

O(nlogn)

还要注意,Timsort在已经排序的阵列上表现良好。

因此,Python利用了Timsort(这是经过一些调整的Mergesort),并且当我几年前查看Java实现时,它也是Mergesort(我认为他们现在也使用Timsort)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.