// 随机找一个数和最后一个数做交换,然后做划分值。划分出来的位置变了概率事件。 O(N*logN)
public static void QuickSort(int[] arr) {
if (arr == null || arr.length < 2) {
return;
}
Process(arr, 0, arr.length - 1);
}
public static void Process(int[] arr, int L, int R) {
if (L >= R) {
return;
}
// L~R随机选取
Swap(arr, L + (int) (Math.random() * (R - L + 1)), R);
int[] equalArea = netherlandsFlag(arr, L, R); // 划分等于区域的左边界,右边界
Process(arr, L, equalArea[0] - 1);// <区
Process(arr, equalArea[1] + 1, R);// >区
}
public static int[] netherlandsFlag(int[] arr, int L, int R) {
if (L > R) { // L...R L>R
return new int[] { -1,-1 };
}
if (L == R) {
return new int[] { L,R };
}
int less = L - 1; // < 区 左边界
int more = R; // > 区 右边界
int index = L;
while (index < more) { // 当前位置index和 >区的边界撞上停止
if (arr[index] == arr[R]) {
index++;
} else if (arr[index] < arr[R]) {
// [index]和<区的下一个数交换,然后<区向右扩一个位置,index++
Swap(arr, ++less,index++);
} else {
// [index]和>区前一个数交换,>区左扩一个位置,index不变因为没有交换完的数没有看过
Swap(arr, index, --more);
}
}
Swap(arr, more, R); // <[R] =[R] >[R] ,和最后一位划分指做交换
// less+1因为小于区域需要加一 才能到等于区域上,而大于区域已经和index撞上了不用加
return new int[] { less + 1, more };
}
public static void Swap(int[] arr, int i, int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}