雅罗斯拉夫斯基的双支点快速排序算法
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)) 性能,导致其他快速排序降低到二次性能,并且通常比传统(单轴)快速排序实现更快。”我猜这就是原因。除此之外,您必须询问将其包含在库中的人。 @ZaviorCollections.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 点枢轴选择 小子数组的插入排序降级 数据属性检测(而不是洗牌)【讨论】:
以上是关于雅罗斯拉夫斯基的双支点快速排序算法的主要内容,如果未能解决你的问题,请参考以下文章