/**
* 单基准快排
* 使用 quickSort(arr,0,arr.length-1) 排序整个数组
*/
private static void quickSort(int[] arr, int left, int right) {
//判断排序条件
if (right <= left)
return;
// 范围内只有两个元素时直接交换
if (right == left + 1) {
if (arr[left] > arr[right]) {
swap(arr, left, right);
}
return;
}
//lt的左边放小于基准值的值
//gt的右边放大于基准值的值
//lt与gt其中一个是基准值
int lt = left, gt = right;
//基准值位置,初始在lt位置
boolean atLt = true;
//从两侧向中心并拢
while (lt < gt) {
//如果左侧大于右侧
if (arr[lt] > arr[gt]) {
//交换位置
swap(arr, lt, gt);
//交换基准值位置
atLt = !atLt;
}
//基准值在左侧,则右侧遍历,否则相反
if (atLt)
--gt;
else
++lt;
}
//继续排序被基准值分隔的两部分
quickSort(arr, left, lt - 1);
quickSort(arr, gt + 1, right);
}
/**
* 双基准快排
* 使用 dualPivotQuickSort(arr,0,arr.length-1) 排序整个数组
*/
public static void dualPivotQuickSort(int[] arr, int left, int right) {
// 判断排序条件
if (right <= left)
return;
// 范围内只有两个元素时直接交换
if (right == left + 1) {
if (arr[left] > arr[right]) {
swap(arr, left, right);
}
return;
}
// left与right分别为左右基准下标(循环时不会改变其下标)
// 使[right]>[left]
if (arr[left] > arr[right]) {
swap(arr, left, right);
}
int lt = left + 1; // 小于left的放在lt左边
int gt = right - 1;// 大于right的放在gt右边
int i = lt; // 循环索引
while (i <= gt) {
if (arr[i] < arr[left]) {
// 小于左基准,放在lt左边
swap(arr, i++, lt++);
} else if (arr[i] > arr[right]) {
// 大于右基准,放在gt右边
swap(arr, i, gt--);
} else {
// 放在lt与i之间
++i;
}
}
// 将基准交换到位,
swap(arr, left, lt - 1);
swap(arr, right, gt + 1);
// 继续将被两个基准值分成的三部分排序
// 此时左基准下标 lt-1 右基准下标 gt+1
dualPivotQuickSort(arr, left, lt - 2);
dualPivotQuickSort(arr, gt + 2, right);
dualPivotQuickSort(arr, lt, gt);
}