雅罗斯拉夫斯基的双支点快速排序算法

Posted

技术标签:

【中文标题】雅罗斯拉夫斯基的双支点快速排序算法【英文标题】:Yaroslavskiy’s dual pivot quick sort algorithm 【发布时间】:2014-02-16 13:58:42 【问题描述】:

我正在研究我发现 here 的双轴快速排序(幻灯片中的第 20 页)

比较:

雅罗斯拉夫斯基平均需要 = 1.9 n ln n。

经典快速排序需要 = 2 n ln n 次比较!

互换:

交换雅罗斯拉夫斯基算法 = 0.6 n ln n

经典 Quicksort=0.3 n ln n 的交换

结果

数据类型-----comp-------交换

int -------------591ns---------802ns

float------------838ns---------873ns

双 --------873ns------------1047ns

char ----------593ns------------837ns

/* 注意:- 以上结果以纳秒为单位,并使用 intel core 2 duo 在 java lang 中执行 */

如果我们将交换成本和比较成本结合起来,那么 Classic Quicksort 会击败 Yaroslavskiy Quicksort 除了在字符串的情况下,我们使用指针数组进行交换需要 88 纳秒。这里 Yaroslavskiy 的算法利用了 1.9 n ln n 比较,因为与字符串的交换相比,比较成本太高了。

我想知道为什么 java 使用 Yaroslavskiy Quicksort ?内置库排序的主要重点是字符串,如果它对其他数据类型不好怎么办?

【问题讨论】:

java在哪里使用这个算法? Collections.sort 根据 javadoc 使用修改过的合并排序 谷歌我可以提供你的公共域代码docjar.com/html/api/java/util/DualPivotQuicksort.java.html “该算法在许多数据集上提供 O(n log(n)) 性能,导致其他快速排序降低到二次性能,并且通常比传统(单轴)快速排序实现更快。”我猜这就是原因。除此之外,您必须询问将其包含在库中的人。 @Zavior Collections.sort 可能使用归并排序,但 Arrays.sort(对原始类型数组进行操作的)使用快速排序。它与排序的稳定性有关 - 基元容器上的稳定与不稳定排序在结果上没有区别,但它对对象有影响。 @Zavior 是的,它是正确的,但仅在最坏的情况下,平均情况如何?对于除字符串以外的其他数据类型,单轴比双轴好 【参考方案1】:

我不知道你的号码是从哪里得到的。根据this page:

证明对于 Dual-Pivot Quicksort 的平均数 比较是2*n*ln(n),平均交换次数是0.8*n*ln(n), 而经典的快速排序算法有2*n*ln(n)1*n*ln(n) 分别。

看起来双轴总是更好。

【讨论】:

【参考方案2】:

我针对许多其他快速排序测试了双 java 的枢轴快速排序。它至少快了 10~15%。除了 doublepivotness,它还使用了许多其他优化:

5 点枢轴选择 小子数组的插入排序降级 数据属性检测(而不是洗牌)

【讨论】:

以上是关于雅罗斯拉夫斯基的双支点快速排序算法的主要内容,如果未能解决你的问题,请参考以下文章

各种排序算法的时间复杂度

[golang] 数据结构-快速排序

八大排序之快速排序

快速排序实现错误

快速排序 - 最坏情况

第四篇快速冒泡选择插入排序