# 解题思路 or 实现原理

快速排序是由东尼·霍尔所发展的一种排序算法。在平均状况下, 排序 n个项目要 Ο(nlogn) 次比较。在最坏状况下则需要 Ο(n2) 次比较, 但这种状况并不常见。事实上, 快速排序通常明显比其他 Ο(nlogn) 算法更快, 因为它的内部循环(inner loop)可以在大部分的架构上很有效率地被实现出来。

快速排序使用分治法(Divide and conquer)策略来把一个串行(list)分为两个子串行(sub-lists)。

快速排序又是一种分而治之思想在排序算法上的典型应用。本质上来看, 快速排序应该算是在冒泡排序基础上的递归分治法。

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

# 算法步骤

  • 从数列中挑出一个元素, 称为'基准' (pivot);

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

  • 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序;

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

quickSort

# 实现代码

/*
 * @Author: Rainy
 * @Date: 2019-11-14 19:25:01
 * @LastEditors: Rainy
 * @LastEditTime: 2019-11-24 20:51:18
 */

import { NumberArrayMap } from 'types';

export function quickSort(arr: NumberArrayMap, left?: number, right?: number) {
  let len: number = arr.length;
  let partitionIndex: number = 0;
  let lIndex: number = typeof left !== 'number' ? 0 : left;
  let rIndex: number = typeof right !== 'number' ? len - 1 : right;

  if (lIndex < rIndex) {
    partitionIndex = partition(arr, lIndex, rIndex);
    quickSort(arr, lIndex, partitionIndex - 1);
    quickSort(arr, partitionIndex + 1, rIndex);
  }
  return arr;
}

function partition(arr: NumberArrayMap, left: number, right: number) {
  let pivot: number = left;
  let index: number = pivot + 1;
  for (let i = index; i <= right; i++) {
    if (arr[i] < arr[pivot]) {
      [arr[i], arr[index]] = [arr[index], arr[i]];
      index++;
    }
  }
  [arr[pivot], arr[index - 1]] = [arr[index - 1], arr[pivot]];
  return index - 1;
}

// export function quickSort(arr: NumberArrayMap): NumberArrayMap {
//   let len = arr.length;
//   if (len < 2) {
//     return arr;
//   }
//   let pivotIndex: number = Math.floor(len / 2);
//   let pivot: number = arr.splice(pivotIndex, 1)[0];
//   let left: NumberArrayMap = [];
//   let right: NumberArrayMap = [];
//   for (let i = 0; i < len; i++) {
//     if (arr[i] < pivot) {
//       left.push(arr[i]);
//     } else {
//       right.push(arr[i]);
//     }
//   }
//   return quickSort(left).concat([pivot], quickSort(right));
// }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

# 参考

quickSort (opens new window)