快速排序的最坏运行情况是 O(n²),比如说顺序数列的快排。但它的平摊期望时间是 O(nlogn),且 O(nlogn) 记号中隐含的常数因子很小,比复杂度稳定等于 O(nlogn) 的归并排序要小很多。所以,对绝大多数顺序性较弱的随机数列而言,快速排序总是优于归并排序。

算法描述

快速排序使用分治法来把一个串(list)分为两个子串(sub-lists)。具体算法描述如下:

  1. 从数列中挑出一个元素,称为 “基准”(pivot);
  2. 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;
  3. 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序;

快速排序(Quick Sort) - 图1

  1. /**
  2. * @author xq
  3. * @date 2022/05/17 15:19
  4. * @describe
  5. */
  6. public class Test {
  7. public static void main(String[] args) {
  8. //给出无序数组
  9. int arr[] = {72, 6, 57, 88, 60, 42, 83, 73, 48, 85};
  10. //输出无序数组
  11. System.out.println(Arrays.toString(arr));
  12. //快速排序
  13. int[] sort = sort(arr);
  14. //输出有序数组
  15. System.out.println(Arrays.toString(sort));
  16. }
  17. public static int[] sort(int[] sourceArray){
  18. // 对 arr 进行拷贝,不改变参数内容
  19. int[] arr = Arrays.copyOf(sourceArray, sourceArray.length);
  20. return quickSort(arr, 0, arr.length - 1);
  21. }
  22. private static int[] quickSort(int[] arr, int left, int right) {
  23. if (left < right) {
  24. int partitionIndex = partition(arr, left, right);
  25. quickSort(arr, left, partitionIndex - 1);
  26. quickSort(arr, partitionIndex + 1, right);
  27. }
  28. return arr;
  29. }
  30. private static int partition(int[] arr, int left, int right) {
  31. // 设定基准值(pivot)
  32. int pivot = left;
  33. int index = pivot + 1;
  34. for (int i = index; i <= right; i++) {
  35. if (arr[i] < arr[pivot]) {
  36. swap(arr, i, index);
  37. index++;
  38. }
  39. }
  40. swap(arr, pivot, index - 1);
  41. return index - 1;
  42. }
  43. private static void swap(int[] arr, int i, int j) {
  44. int temp = arr[i];
  45. arr[i] = arr[j];
  46. arr[j] = temp;
  47. }
  48. }

快速排序(Quick Sort) - 图2