算法步骤

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

动图演示

quickSort.gif

代码

  1. public class QuickSort {
  2. public int[] sort(int[] sourceArray) {
  3. // 对 arr 进行拷贝,不改变参数内容
  4. int[] arr = Arrays.copyOf(sourceArray, sourceArray.length);
  5. return quickSort(arr, 0, arr.length - 1);
  6. }
  7. private int[] quickSort(int[] arr, int left, int right) {
  8. if (left < right) {
  9. int partitionIndex = partition(arr, left, right);
  10. quickSort(arr, left, partitionIndex - 1);
  11. quickSort(arr, partitionIndex + 1, right);
  12. }
  13. return arr;
  14. }
  15. private int partition(int[] arr, int left, int right) {
  16. // 设定基准值(pivot)
  17. int pivot = left;
  18. int index = pivot + 1;
  19. for (int i = index; i <= right; i++) {
  20. if (arr[i] < arr[pivot]) {
  21. swap(arr, i, index);
  22. index++;
  23. }
  24. }
  25. swap(arr, pivot, index - 1);
  26. return index - 1;
  27. }
  28. private void swap(int[] arr, int i, int j) {
  29. int temp = arr[i];
  30. arr[i] = arr[j];
  31. arr[j] = temp;
  32. }
  33. }

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