阅读更多
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