快速排序重点在于怎样在O(n)时间复杂度将数组分成左右两部分,左边全小于pivot,右边全大于等于pivot,且最后要将pivot放到合适的位置
快速排序经典算法:
public static void quick_sort(int[] arr, int l, int r) {
if (l < r) {
int mid = partition(arr, l, r);
quick_sort(arr, l, mid - 1);
quick_sort(arr, mid + 1, r);
}
}
// l 作为pivot
private static int partition(int[] arr, int l, int r) {
int pivot_val = arr[l];
while (l < r) {
while (arr[r] >= pivot_val && l < r) {
r--;
}
if (l < r) {
arr[l++] = arr[r];
}
while (arr[l] <= pivot_val && l < r) {
l++;
}
if (l < r) {
arr[r--] = arr[l];
}
}
arr[l] = pivot_val;
return l;
}
// r 作为pivot
private static int partition1(int[] arr, int l, int r) {
int pivot = arr[r];
while (l < r) {
while (l < r && arr[l] < pivot) {
l++;
}
if (l < r) {
arr[r--] = arr[l];
}
while (l < r && arr[r] >= pivot) {
r--;
}
if (l < r) {
arr[l++] = arr[r];
}
}
arr[l] = pivot;
return l;
}
// mid 作为pivot
private static int partition2(int[] arr, int l, int r) {
int mid = l + ((r - l) >> 1);
int pivot_val = arr[mid];
while (l < r) {
while (l < r && arr[l] < pivot_val) {
l++;
}
while (l < r && pivot_val <= arr[r]) {
r--;
}
if (l < r) {
// mid下标在被替换之后 需记录对应位置
if (l == mid) {
mid = r;
} else if (r == mid) {
mid = l;
}
swap(arr, l, r);
}
}
// pivot放到合适的位置
if (arr[l] > pivot_val) {
swap(arr, l, mid);
}
return l;
}
快速排序三路算法:
三路算法添加随机过程可避免 经典算法中 遇到已拍好序的数据时间复杂度退化为O(n*n)
public static void three_quick_sort(int[] arr, int l, int r) {
if (l < r) {
int mid = three_mid_index(arr, l, r);
three_quick_sort(arr, l, mid - 1);
three_quick_sort(arr, mid + 1, r);
}
}
private static int three_mid_index(int[] arr, int l, int r) {
int index = l + (int)(Math.random() * (r - l + 1));
swap(arr, index, r);
int small = l - 1;
for (index = l; index < r; index++) {
if (arr[index] < arr[r]) {
small++;
if (small != index) {
swap(arr, small, index);
}
}
}
swap(arr, small + 1, r);
return small + 1;
}
public static void swap(int[] arr, int l, int r) {
int temp = arr[l];
arr[l] = arr[r];
arr[r] = temp;
}
快速排序非递归实现
public static void stack_quick_sort(int[] arr, int l, int r) {
Stack<Integer> stack = new Stack<>();
do {
if (!stack.isEmpty()) {
l = stack.pop();
r = stack.pop();
}
// three_mid_index mid_index 都可以
int mid_idx = mid_index(arr, l, r);
if (l < mid_idx - 1) {
stack.push(mid_idx - 1);
stack.push(l);
}
if (mid_idx + 1 < r) {
stack.push(r);
stack.push(mid_idx + 1);
}
} while (!stack.isEmpty());
}
private static int mid_index(int[] arr, int l, int r) {
int pivot_val = arr[l];
while (l < r) {
while (arr[r] >= pivot_val && l < r) {
r--;
}
if (l < r) {
arr[l++] = arr[r];
}
while (arr[l] <= pivot_val && l < r) {
l++;
}
if (l < r) {
arr[r--] = arr[l];
}
}
arr[l] = pivot_val;
return l;
}