1、快速排序的原理
选择一个关键值作为基准值,比基准值小的都在左边序列(仍是无序的),比基准值大的都在右边序列(也是无序的),基准值的选取:一般为第一个元素。
第一次循环:先从后往前比较,用基准值和最后一个值比较,如果比基准值小的交换位置。如果没有就继续比较下一个,直到找到第一个比基准值小的值才交换。 找到这个值之后,就从前往后开始比较,如果有比基准值大的,交换位置,没有就继续比较下一个,直到找到第一个比基准值大的值才交换。第一次 循环结束条件 :从前往后的索引指针>从后往前的索引指针,然后递归排序前后两段‘子组’。
2、动图实现快排
3、具体实现代码:
import java.util.Arrays;
public class QuickSortDemo {
public static void main(String[] args) {
int[] num = {3,44,38,5,47,15,36,26,27,2,46,4,19,50,48};
System.out.println("未排序:" + Arrays.toString(num));
quickSort(num, 0, num.length - 1);
System.out.println("排序后:" + Arrays.toString(num));
}
public static void quickSort(int[] arr, int start, int end) {
if (arr == null || start >= end) return;
int i = start, j = end;
int pivotKey = arr[start]; // 用子表的第一个记录做基准
// 从表的两端交替向中间扫描
while (i < j) {
// 顺序很重要,要先从右边开始找
while (i < j && arr[j] >= pivotKey) j--;
if (i < j) arr[i++] = arr[j]; //用比基准小的记录替换低位记录
while (i < j && arr[i] <= pivotKey) i++;
if (i < j) arr[j--] = arr[i]; // 用比基准大的记录替换高位记录
}
arr[i] = pivotKey; // 将基准数值替换回 arr[i]
quickSort(arr, start, i - 1); // 递归排序比开始时基准数低的'子数组'
quickSort(arr, i + 1, end); // 递归排序比开始时基准数高的'子数组'
}
}
排序结果:
4、复杂度分析:
(1)时间复杂度
① 最好和平均时间复杂度
最好情况是指选择的基准关键字为待排序的记录的中间值。此时进行比较次数总共为 nlogn,所以最好情况下快速排序的时间复杂度为O(nlogn)。
快速排序的平均时间复杂度为O(nlogn)。
在所有平均时间复杂度为O(nlogn)的算法中,快速排序的平均性能是最好的。
② 最坏时间复杂度
最坏情况是指每次区间划分的结果都是基准关键字的左边(或右边)序列为空,而另一边区间中的记录仅比排序前少了一项,即选择的关键字是待排序记录的最小值或最大值。最坏情况下快速排序的时间复杂度为O(n^2)。
(2)空间复杂度
快速排序的过程中需要一个栈空间来实现递归。最好情况递归树的深度为log2n,其空间复杂度也就是O(nlogn);平均情况空间复杂度为O(nlogn);最坏情况下,需要进行 n-1次递归,其空间复杂度为O(n)。