阅读更多
1 前言
Java中Arrays.sort排序方法对于基本类型的排序采用的是双轴快速排序。本篇博客主要分析JDK源码
2 常量
1 | /** |
MAX_RUN_COUNT
:run数量的最大值,如果超过这个值,那么便认为数组不是特别的有序MAX_RUN_LENGTH
:run长度的最大值QUICKSORT_THRESHOLD
:如果数组长度小于这个值,那么快排的效率会比归并排序的效率要高INSERTION_SORT_THRESHOLD
:如果数组长度小于这个值,那么插入排序的效率会比快排的效率要高COUNTING_SORT_THRESHOLD_FOR_BYTE
:对于字节数组而言,如果长度大于这个数值,那么用计数排序效率比较高,因为额外的内存空间是确定的,256COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR
:对于char或者short而言,如果数组长度大于这个数值,那么计数排序效率会比较高
从这几个常量就能清晰地看出,DualPivotQuickSort对于不同的基本类型的排序方式是不同的,对于short、char以及byte等16bit或者8bit的基本类型而言,计数排序不会造成特别大的空间开销。而对于其他基本类型,比如int,long,float,double等。则会根据数组的长度来选择相应的排序算法,包括插入排序、快速排序和归并排序
3 方法
3.1 sort
参数说明
- a:待排序的数组
- left:左边界,闭区间
- right:右边界,闭区间
- work:
- workBase:
- workLen
1 | /** |
下面给一个流程图
flowchart TD st(["开始"]) en1(["结束"]) en2(["结束"]) en3(["结束"]) cond1{"QUICKSORT_THRESHOLD ?"} op1["利用sort方法进行排序"] cond2{"重复元素较少 ?"} cond3{"存在有序片段 ?"} op2["利用sort方法进行排序"] op3["类似于Timsort的归并排序"] st --> cond1 cond1 --> |no| op1 op1 --> en1 cond1 --> |yes| cond2 cond2 --> |yes| cond3 cond2 --> |no| op2 cond3 --> |yes| op3 cond3 --> |no| op2 op2 --> en2 op3 --> en3
3.2 sort
双轴快速排序
参数说明
- a:待排序数组
- left:待排序序列范围的左边界
- right:待排序序列范围的右边界
- leftmost:指定范围是否在数组最左边
1 | /** |
下面给一个流程图
flowchart TD st(["开始"]) en1(["结束"]) en2(["结束"]) en3(["结束"]) cond1{"INSERTION_SORT_THRESHOLD ?"} cond2{"leftmost ?"} op1["经典插入排序"] op2["pair-插入排序"] op3["找出均匀分布的5个位置e1-e5"] op4["冒泡排序e1-e5"] cond3{"e1-e5严格单调 ?"} op5["以e2和e4为双轴进行第一次双轴partition"] op6["left-part(小于pivot1的部分)递归sort"] op7["right-part(大于pivot2的部分)递归sort"] cond4{"center-part过大 ?"} op8["进行第二次双轴partition"] op9["center-part递归sort"] op10["以e3位单轴进行3-way-partition"] op11["left-part(小于pivot的部分)递归sort"] op12["right-part(大于pivot的部分)递归sort"] st --> cond1 cond1 --> |no| cond2 cond2 --> |yes| op1 cond2 --> |no| op2 op1 --> en1 op2 --> en1 cond1 --> |yes| op3 op3 --> op4 op4 --> cond3 cond3 --> |yes| op5 op5 --> op6 op6 --> op7 op7 --> cond4 cond4 --> |yes| op8 op8 --> op9 cond4 --> |no| op9 op9 --> en2 cond3 --> |no| op10 op10 --> op11 op11 --> op12 op12 --> en3