快速排序

快速排序是由东尼·霍尔所发展的一种排序算法。在平均状况下,排序 n 个项目要 Ο(nlogn) 次比较。在最坏状况下则需要 Ο(n2) 次比较,但这种状况并不常见。事实上,快速排序通常明显比其他 Ο(nlogn) 算法更快,因为它的内部循环(inner loop)可以在大部分的架构上很有效率地被实现出来。 快速排序使用分治法(Divide and conquer)策略来把一个串行(list)分为两个子串行(sub-lists)。 快速排序又是一种分而治之思想在排序算法上的典型应用。本质上来看,快速排序应该算是在冒泡排序基础上的递归分治法。 快速排序的名字起的是简单粗暴,因为一听到这个名字你就知道它存在的意义,就是快,而且效率高!它是处理大数据最快的排序算法之一了。虽然 Worst Case 的时间复杂度达到了 O(n²),但是人家就是优秀,在大多数情况下都比平均时间复杂度为 O(n logn) 的排序算法表现要更好,可是这是为什么呢,我也不知道。好在我的强迫症又犯了,查了 N 多资料终于在《算法艺术与信息学竞赛》上找到了满意的答案:

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

1. 算法步骤

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

递归的最底部情形,是数列的大小是零或一,也就是永远都已经被排序好了。虽然一直递归下去,但是这个算法总会退出,因为在每次的迭代(iteration)中,它至少会把一个元素摆到它最后的位置去。

2. 动图演示

动图演示

3. JavaScript 代码实现

  1. 1. function quickSort(arr, left, right) {
  2. 2. var len = arr.length,
  3. 3. partitionIndex,
  4. 4. left = typeof left != 'number' ? 0 : left,
  5. 5. right = typeof right != 'number' ? len - 1 : right;
  6. 6. 7. if (left < right) {
  7. 8. partitionIndex = partition(arr, left, right);
  8. 9. quickSort(arr, left, partitionIndex-1);
  9. 10. quickSort(arr, partitionIndex+1, right);
  10. 11. }
  11. 12. return arr;
  12. 13. }
  13. 14. 15. function partition(arr, left ,right) { // 分区操作
  14. 16. var pivot = left, // 设定基准值(pivot)
  15. 17. index = pivot + 1;
  16. 18. for (var i = index; i <= right; i++) {
  17. 19. if (arr[i] < arr[pivot]) {
  18. 20. swap(arr, i, index);
  19. 21. index++;
  20. 22. }
  21. 23. }
  22. 24. swap(arr, pivot, index - 1);
  23. 25. return index-1;
  24. 26. }
  25. 27. 28. function swap(arr, i, j) {
  26. 29. var temp = arr[i];
  27. 30. arr[i] = arr[j];
  28. 31. arr[j] = temp;
  29. 32. }
  30. 33. function partition2(arr, low, high) {
  31. 34. let pivot = arr[low];
  32. 35. while (low < high) {
  33. 36. while (low < high && arr[high] > pivot) {
  34. 37. --high;
  35. 38. }
  36. 39. arr[low] = arr[high];
  37. 40. while (low < high && arr[low] <= pivot) {
  38. 41. ++low;
  39. 42. }
  40. 43. arr[high] = arr[low];
  41. 44. }
  42. 45. arr[low] = pivot;
  43. 46. return low;
  44. 47. }
  45. 48. 49. function quickSort2(arr, low, high) {
  46. 50. if (low < high) {
  47. 51. let pivot = partition2(arr, low, high);
  48. 52. quickSort2(arr, low, pivot - 1);
  49. 53. quickSort2(arr, pivot + 1, high);
  50. 54. }
  51. 55. return arr;
  52. 56. }

4. Python 代码实现

  1. 1. def quickSort(arr, left=None, right=None):
  2. 2. left = 0 if not isinstance(left,(int, float)) else left
  3. 3. right = len(arr)-1 if not isinstance(right,(int, float)) else right
  4. 4. if left < right:
  5. 5. partitionIndex = partition(arr, left, right)
  6. 6. quickSort(arr, left, partitionIndex-1)
  7. 7. quickSort(arr, partitionIndex+1, right)
  8. 8. return arr
  9. 9. 10. def partition(arr, left, right):
  10. 11. pivot = left
  11. 12. index = pivot+1
  12. 13. i = index
  13. 14. while i <= right:
  14. 15. if arr[i] < arr[pivot]:
  15. 16. swap(arr, i, index)
  16. 17. index+=1
  17. 18. i+=1
  18. 19. swap(arr,pivot,index-1)
  19. 20. return index-1
  20. 21. 22. def swap(arr, i, j):
  21. 23. arr[i], arr[j] = arr[j], arr[i]

5. Go 代码实现

  1. 1. func quickSort(arr []int) []int {
  2. 2. return _quickSort(arr, 0, len(arr)-1)
  3. 3. }
  4. 4. 5. func _quickSort(arr []int, left, right int) []int {
  5. 6. if left < right {
  6. 7. partitionIndex := partition(arr, left, right)
  7. 8. _quickSort(arr, left, partitionIndex-1)
  8. 9. _quickSort(arr, partitionIndex+1, right)
  9. 10. }
  10. 11. return arr
  11. 12. }
  12. 13. 14. func partition(arr []int, left, right int) int {
  13. 15. pivot := left
  14. 16. index := pivot + 1
  15. 17. 18. for i := index; i <= right; i++ {
  16. 19. if arr[i] < arr[pivot] {
  17. 20. swap(arr, i, index)
  18. 21. index += 1
  19. 22. }
  20. 23. }
  21. 24. swap(arr, pivot, index-1)
  22. 25. return index - 1
  23. 26. }
  24. 27. 28. func swap(arr []int, i, j int) {
  25. 29. arr[i], arr[j] = arr[j], arr[i]
  26. 30. }

6. C++版

  1. 1. //严蔚敏《数据结构》标准分割函数
  2. 2. Paritition1(int A[], int low, int high) {
  3. 3. int pivot = A[low];
  4. 4. while (low < high) {
  5. 5. while (low < high && A[high] >= pivot) {
  6. 6. --high;
  7. 7. }
  8. 8. A[low] = A[high];
  9. 9. while (low < high && A[low] <= pivot) {
  10. 10. ++low;
  11. 11. }
  12. 12. A[high] = A[low];
  13. 13. }
  14. 14. A[low] = pivot;
  15. 15. return low;
  16. 16. }
  17. 17. 18. void QuickSort(int A[], int low, int high) //快排母函数
  18. 19. {
  19. 20. if (low < high) {
  20. 21. int pivot = Paritition1(A, low, high);
  21. 22. QuickSort(A, low, pivot - 1);
  22. 23. QuickSort(A, pivot + 1, high);
  23. 24. }
  24. 25. }

7. Java 代码实现

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

8. PHP 代码实现

  1. 1. function quickSort($arr)
  2. 2. {
  3. 3. if (count($arr) <= 1)
  4. 4. return $arr;
  5. 5. $middle = $arr[0];
  6. 6. $leftArray = array();
  7. 7. $rightArray = array();
  8. 8. 9. for ($i = 1; $i < count($arr); $i++) {
  9. 10. if ($arr[$i] > $middle)
  10. 11. $rightArray[] = $arr[$i];
  11. 12. else
  12. 13. $leftArray[] = $arr[$i];
  13. 14. }
  14. 15. $leftArray = quickSort($leftArray);
  15. 16. $leftArray[] = $middle;
  16. 17. 18. $rightArray = quickSort($rightArray);
  17. 19. return array_merge($leftArray, $rightArray);
  18. 20. }

整理人:豆包AI助手