JDK的快速排序算法实现DualPivotQuicksort

来源:互联网 发布:大漠骑兵网络 编辑:程序博客网 时间:2024/06/06 02:04

从JDK7开始采用这种双Pivot的快速排序算法,这种算法通常会比传统单Pivot的快排算法效率更高。本文采用JDK8的源码进行分析。
具体流程如下:
1.需要排序的数组为a,判断数组的长度是否大于286,大于使用归并排序(merge sort),否则执行2。
2.判断数组长度是否小于47,小于则采用插入排序,否则执行3。
3.采用近似算法计算数组长度的1/7

int seventh = (length >> 3) + (length >> 6) + 1;

4.取出5个点

int e3 = (left + right) >>> 1; // 中位数int e2 = e3 - seventh;int e1 = e2 - seventh;int e4 = e3 + seventh;int e5 = e4 + seventh;

5.将这5个元素进行插入排序
6.选取a[e2],a[e4]分别作为pivot1,pivot2。由于步骤5进行了排序,所以必有pivot1 < pivot2。
7.接下来定义3个指针,分别是less,k,great。先说一下最终结果,less和great将数组分为3个部分,分别是小于less的,大于less小于great的元素和大于great的元素。
如何达到这个结果呢,初始时,less和great分别指向数组起始的元素和结束的元素。此时,所有的元素在less和great之间,即待处理的元素。随着程序的进行,小于less的元素逐步移动到less左边,大于great的元素移动到great右边。
另外有一个指针k表示处理到哪个元素了,初始值为less,结束值为great(这里的great是会动态改变的,但是大于great的元素一定是处理过的)
DualPivot快排图解
8.将a[k]分别与pivot1,pivot2比较。如果小于pivot1,则将a[k]与a[less]对调,同时k++。如果大于pivot2,则执行9;否则执行10。
9.将a[great]分别与pivot1,pivot2比较。如果a[great]大于pivot2,则递减great,直到大于pivot2的条件不满足或者k==great。如果a[great]小于pivot1,则将a[great]换到小于less的区域。如果a[great]大于pivot1,则说明位于中间区域,将a[great]与a[k]对调。great–。
10.k++,如果k>great,说明处理完成,则执行11,否则继续执行8;
11.由于前面的操作,还未将pivot1,pivot2这2个元素放对位置,所以还需要将a[less - 1]移动到队头,pivot1移动到(less - 1)的位置,将a[great +1]移动到队尾,pivot2移动到(great +1)的位置。
12.至此,已经达到步骤7描述的最终结果,将数组分为了3个区域。对较小的区域和较大的区域递归执行步骤2。判断中间的区域是否过大,如果是,则执行13,否则递归执行步骤2。
13.将等于pivot1或者pivot2的元素移动到两边,然后递归执行步骤2。

1 0
原创粉丝点击