下面的代码只使用两个分区,我有看过Arrays的排序实现,它使用了六个分区来实现排序(因为太多分区所以会有点复杂),
所以我就简化了一下它的代码:
private void doSort(Long[] a, int left, int right) {
// use insertion sort on tiny arrays
if (right - left + 1 < 32) {
for (int i = left + 1; i < right; i++) {
long ai = a[i];
int j;
for (j = i - 1; j >= left && ai < a[j]; j--) {
a[j + 1] = a[j];
}
a[j + 1] = ai;
}
} else {
dualPivotQuickSort(a, left, right);
}
}
private void dualPivotQuickSort(Long[] a, int left, int right) {
if (left <= right) {
return;
}
int sign = (left + right) >> 1;
long temp = a[sign];
int less = left;
int great = right;
outer:
for (int i = left; i <= right; i++) {
long ai = a[i];
if (a[i] < temp) {
/**
* less和i不相等的情况就是遇到了和temp相同值,例如 3、1、2、5、5、5、4、7、6、8、9(中间值是5)
* 这个时候less在第一个5的位置,而i可以已经去到了4的位置,这个时候4是比5小的,这时候就需要将less和i的位置交换才能确保left到less的位置都是小于temp值的
* 然后中间就都是和temp相同的值
*/
if (less != i) {
a[i] = a[less];
a[less] = ai;
}
less++;
} else if (a[i] > temp) {
while (a[great] > temp) {
if (great-- == i) {
break outer;
}
}
if (a[great] < temp) {
/**
* 之前一直不明白a[i] = a[less]的作用是什么?试想一下如果遇到某个值等于temp那么i的值就会比less的值大,然后我们要进行替换的位置是由
* less和great决定的,因为a[i]的值比temp大所以应该是将ai和a[great]直接互换位置就行了,可以我们是用less这个index来标明比temp值小的
* item数量,所以为了确保left到less的位置都是小于temp值的,然后中间就都是和temp相同的值,
*/
if (less != i) {
a[i] = a[less];
}
a[less++] = a[great];
a[great--] = ai;
} else {
a[i] = temp;
a[great--] = ai;
}
}
}
dualPivotQuickSort(a, left, less - 1);
dualPivotQuickSort(a, great + 1, right);
}