Quicksort是一个众所周知的问题,当数据集处于或几乎按排序顺序时,性能会大幅降低。在这种情况下,插入排序通常非常慢,很容易成为最佳选择。问题是知道何时使用哪个。
是否有可用于运行数据集的算法,应用比较因子,并返回有关数据集与排序顺序的接近程度的报告?我更喜欢Delphi / Pascal,但如果示例不是太复杂,我可以阅读其他语言。
答案 0 :(得分:10)
正如你所期望的那样。三次中值技术意味着快速排序的最坏情况行为不会出现在排序数据中,而是出现在不太明显的情况下。
Introsort非常令人兴奋,因为它完全避免了quicksort的二次最坏情况。而不是你的自然问题,“我如何检测到数据几乎已经排序”,它实际上是在问自己是否正在进行,“这需要花费太长时间吗?”。如果答案是肯定的,它会从快速排序切换到高级排序。
Timsort将合并排序与插入排序相结合,并且对已排序或反向排序的数据以及包含已排序或反向排序的子集的数据执行得非常好。
因此,你的问题的答案很可能是,“你不需要预先通过分析,你需要一种自适应排序算法”。
答案 1 :(得分:3)
还有SmoothSort,它实现起来相当棘手,但它在O(N log N)到O(N)之间变化,具体取决于数据的排序方式。
http://en.wikipedia.org/wiki/Smoothsort
冗长棘手的PDF: http://www.cs.utexas.edu/users/EWD/ewd07xx/EWD796a.PDF
但是,如果您的数据非常庞大并且您必须以串行方式访问它,那么mergesort可能是最好的。它总是O(N log N),并且具有出色的“局部性”特性。
答案 2 :(得分:0)
我没有听说过任何预分类分析,但我的意见是,如果您要通过数据集进行分析,那么您已经在削减整体分拣时间的性能。
答案 3 :(得分:0)
一种可能的解决方案是在当前排序范围内(在QuickSort操作期间)获取first,last和middle元素,并选择中间元素作为pivot元素。
答案 4 :(得分:0)
为了完全分析决定使用哪种算法的目的,您将要做几乎排序的工作。你可以做一些事情,比如检查一小部分随机但增加的指数值(即分析一小部分项目)。
答案 5 :(得分:0)
您仍然需要浏览所有记录以确定其是否已排序,以便提高性能,从您的第一条记录开始并运行其余记录,直到您发现未正确排序的某些内容,或者到达结束时名单。如果您发现未命中,则只对从该位置到结尾的项目进行排序(因为列表的开头已经排序)。
在第二部分的每个项目中,查看该项目是否为<比第一部分中的最后一个元素,如果是这样,只使用插入排序到第一部分。否则Quicksort将对抗第二部分中的所有其他项目。这样,排序就特定情况进行了优化。
答案 6 :(得分:0)
QuickSort仅在数据集很大并且已经大部分排序时才会出现问题,我会使用以下启发式方法(等待完整的解决方案):
如果数据集大小低于阈值,请不要打扰。
如果您对记录(项目)有快速(索引)访问权限,请在每N条记录中获取一条记录,并查看它们是否已经排序。对于小样本应该足够快,然后您可以决定是否使用快速排序。
答案 7 :(得分:0)
提出一个人们尚未提出的概念点:Quicksort是一种常识性的分而治之算法,在极少数情况下会出现明显的错误。假设您要对一堆学生论文进行排序。 (我必须要做一些规律性。)在快速排序算法中,你选择一些纸张,即枢轴。然后根据它们是在枢轴之前还是之后划分其他纸张。然后用两个子弹重复一遍。什么是虫子?枢轴可以是靠近列表一端而不是中间的名称,因此将它分成两堆并不会有太大的作用。
合并排序是另一种以不同顺序工作的分而治之算法。您可以在线性时间内合并两个排序列表。将论文分成两个相等或几乎相等的桩,然后递归排序每一个,然后合并。合并排序没有任何错误。快速排序比合并排序更受欢迎的一个原因是历史:Quicksort很快(通常)并且它没有任何额外的内存。但是现在,保存比较比保存内存更重要,实际的重新排列通常是通过置换指针来抽象的。如果事情总是这样,那么我怀疑合并排序会比quicksort更受欢迎。 (并且可能在名称中添加“快速”是良好的推销技巧。)