以前有人见过这种改进吗?

时间:2010-01-20 23:06:25

标签: c++ algorithm sorting quicksort

5 个答案:

答案 0 :(得分:7)

Vladimir Yaroslavskiy | 9月11日12:35 使用新的Dual-Pivot Quicksort替换java.util.Arrays中的Quicksort

访问http://permalink.gmane.org/gmane.comp.java.openjdk.core-libs.devel/2628

答案 1 :(得分:5)

要回答你的问题,我以前没有见过这种方法。我不打算对您的代码进行分析并执行其他艰苦的工作,但以下可能是正式提出算法的后续步骤/注意事项。在现实世界中,实现排序算法:

良好的可扩展性/复杂性低开销

缩放和开销很明显,很容易衡量。在分析排序时,除了时间衡量比较和交换的数量。大文件的性能也取决于磁盘搜索时间。例如,合并排序适用于带磁盘的大型文件。 (另见Quick Sort Vs Merge Sort

广泛的输入和良好的性能

有很多数据需要排序。众所周知,应用程序可以按模式生成数据,因此在某些模式下使排序具有抵御性能差的重要性非常重要。您的算法针对重复数字进行优化。如果所有数字都重复但只有一次(即seq 1000>文件; seq 1000>>文件; shuf文件)怎么办?如果数字已经排序怎么办?向后排序? 1,2,3,1,2,3,1,2,3,1,2,3的模式怎么样? 1,2,3,4,5,6,7,6,5,4,3,2,1? 7,6,5,4,3,2,1,2,3,4,5,6,7?在其中一种常见情况下表现不佳是一个交易破坏者!在与已发布的通用算法进行比较之前,准备好这种分析是明智的。

病理表现低风险

在所有输入的排列中,有一个比其他输入更糟糕。表现比平均水平差多少?有多少排列会提供类似的不良表现?

祝你下一步好运!

答案 2 :(得分:0)

这是一个伟大的改进,我相信如果你期望很多相同的对象,它已经被特别实现了。有很多这种墙壁的微调。

如果我理解你所写的所有内容,那么它通常不会“知道”的原因是它确实提高了基本的O(n2)性能。这意味着,对象数量增加一倍,时间增加四倍。除非所有对象都相同,否则您的改进不会改变这一点。

答案 3 :(得分:-1)

std:排序并不是很快。

以下是我将其与随机并行非递归快速排序进行比较的结果:

pnrqSort(longs): 。:。1 000 000 36ms(每毫秒物品数:27777.8)

。:。5 000 000 140ms(每毫秒物品数:35714.3)

。:。10 000 000 296ms(每毫秒物品数:33783.8)

。:。50 000 000 1s 484ms(每毫秒物品数:33692.7)

。:。100 000 000 2s 936ms(每ms的数量:34059.9)

。:。250 000 000 8s 300ms(每毫秒物品数:30120.5)

。:。400 000 000 12s 611ms(每个项目数:31718.3)

。:。500 000 000 16s 428ms(每ms的数量:30435.8)

的std ::排序(多头) 。:。1 000 000 134ms(每毫秒物品数:7462.69)

。:。5 000 000 716ms(每个项目数:6983.24)

std :: longs的排序

1 000 000 511ms(每毫秒物品数:1956.95)

2 500 000 943ms(每件物品数:2651.11)

由于你有额外的方法,它将导致更多的堆栈使用,这将最终减慢速度。为什么使用3的中位数,我不知道,因为它是一种不好的方法,但随机枢轴点快速排序从未出现统一或预先排序数据的大问题,并且没有故意中位数为3杀手数据的危险。

答案 4 :(得分:-1)

似乎没有人喜欢你的算法,但我确实如此。 在我看来,这是一种以现在的方式重新制作经典快速排序的好方法 安全使用高度重复的元素。 你的q1和q2子算法,在我看来实际上是SAME算法 除了<和< =运算符互换和其他一些东西,如果你 想要允许你为此编写更短的伪代码(虽然可能更少 有效)。建议你阅读  JL Bentley,MD McIlroy:设计排序功能
 软件 - 实践与经验23,11(1993年11月)1249-1265 电子版在这里  http://www.skidmore.edu/~meckmann/2009Spring/cs206/papers/spe862jb.pdf 看他们快速通过的测试。你的想法可能更好,更好, 但它需要运行他们尝试的各种测试的挑战,使用一些 特别是枢轴选择方法。找到一个通过所有测试而不会遭受二次运行时间的测试。然后,如果你的算法比他们的算法更快更好,那么你显然会有一个有价值的贡献。

他们用来生成枢轴的“Tukey Ninther”在我看来也是可用的 并且会自动使二次时最坏情况在实践中出现变得非常困难。 我的意思是,如果你只使用3的中位数并尝试数组的中间和两个末端元素 你的三个,然后一个对手将使初始阵列状态增加然后减少然后你会在一个不太难以置信的输入上以二次运行时落在你的脸上。但是对于Tukey Ninther的9个元素,我很难构建 一个看似合理的输入,会使用二次运行时伤害你。

另一种观点&一条建议: 想想q1拆分数组的组合,然后q2拆分右子阵, 作为单个q12算法产生阵列的3路分裂。现在,你需要递归 在3个子阵列上(如果两个枢轴碰巧相等,则只有2个)。现在总是 在你要报告的子阵列的最小数据上递归,FIRST和 最大的LAST - 并没有将这个最大的一个实现为递归,而是保持在相同的例程中并通过缩小窗口循环回到顶部。那样 你在q12中的递归调用比你想要的少1,但主要的一点是, 现在,递归堆栈的长度超过O(logN)是不可能的。 好?这解决了另一个烦人的最坏情况问题,快速排序可能会受到影响,同时也在制造 你的代码无论如何都要快一点。