快速排序,又称分区交换排序,简称快排,是一种被广泛运用的排序算法
基本思想
通过将待排记录分隔成独立的两部分,其中一部分记录比关键字小的,另一部分记录比关键字大的,分别对这两部分记录进行排序,以达到整个序列有序
实现逻辑
快速排序使用分治法策略来把一个序列分为两个子序列
- 从数列中挑出一个元素,称为 “基准”(pivot)
- 比基准值小的摆放在基准左边,比基准值大的摆在基准右边
- 递归把左边和右边的子数排序
复杂度
最佳空间复杂度:O(logN)
最差空间复杂度:O(N)
最佳时间复杂度:O(N*logN)
最差时间复杂度:O(N^2)
动图演示
流程图
java
public static void main(String[] args) {
int[] arr = {3, 5, 6, 3, 4, 5, 2, 6, 9, 0};
quickSort(arr);
System.out.println(Arrays.toString(arr));
}
// 快速排序入口函数
public static void quickSort(int[] arr) {
if (arr == null || arr.length < 2) return;
quickSort(arr, 0, arr.length - 1);
}
// 快速排序递归函数,对arr[L..R]进行排序
public static void quickSort(int[] arr, int L, int R) {
if (L >= R) return;
// 快排3.0 取随机数作为基准值,跟数组最后一位做交换
// 随机这一下,常数时间比较大
// 但只有这一下随机,才能在概率上把快速排序的时间复杂度收敛到O(n * logn)
swap(arr, L + (int) (Math.random() * (R - L + 1)), R);
int[] p = partition(arr, L, R);
// 对小于基准值的子数组进行递归排序
quickSort(arr, L, p[0] - 1);
// 对大于基准值的子数组进行递归排序
quickSort(arr, p[1] + 1, R);
}
// 分区函数,处理arr[L..R]的数组,返回等于区域的左右边界
public static int[] partition(int[] arr, int L, int R) {
// 小于区域的右边界 从-1开始
int less = L - 1;
// 大于区域的左边界 从arr.length-1开始
int more = R;
while (L < more) { // 当前数的位置为L,基准值为arr[R]
if (arr[L] < arr[R]) { // 当前数小于基准值
// 将当前数放入小于区域,并将L向右移动
swap(arr, ++less, L++);
} else if (arr[L] > arr[R]) { // 当前数大于基准值
// 将当前数放入大于区域,并将L向右移动
swap(arr, --more, L);
} else {
// 当前数等于基准值,将L向右移动
L++;
}
}
// 将基准值放入等于区域的右边界位置
swap(arr, more, R);
// 返回等于区域的左右边界
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;
}
文档信息
- 本文作者:carpe
- 本文链接:https://carpedx.com/wiki/algorithm-quick-sort/
- 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)