Skip to content
本页目录

快速排序

基本思想:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

算法过程描述:

  1. 创建首尾指针,左指针指向数组第一个值,右指针指向数组最后一个值;
  2. 从数组中随机取出基准数pivot,并将基准数换到数组开头;
  3. 当左指针小于右指针时:
    1. 移动右指针,直到找到第一个比基准数小的值的下标;
    2. 移动左指针,直到找到第一个比基准数大的值的下标;
    3. 交换左右指针处的值。
  4. 遍历完成后,数组被分成了左右两个区域,此时基准数位于左(右)指针处;
  5. 将左右两个区域视为两个数组,重复步骤1步骤3,直到排序完成。

原地快排

JavaScript
const quickSort = (A, s = 0, e = A.length - 1) => {
  let [l, r] = [s, e] // 定义首尾指针
  const idx = ~~(s + Math.random() * (e - s + 1));  //随机选择基准数
  [A[s], A[idx]] = [A[idx], A[s]] // 将基准数换到数组开头
  while (l < r) {
    // 移动右指针找到比基准数小的数
    while (l < r && A[r] >= A[s]) r--
    // 移动左指针找到比基准数大的数
    while (l < r && A[l] <= A[s]) l++
    [A[l], A[r]] = [A[r], A[l]]
  }
  // 由于此时的l/r就是基准值的下标,所以更新基准值
  [A[s], A[l]] = [A[l], A[s]]
  if (s < l - 1) {
    // 左闭右闭区间
    quickSort(A, s, l - 1)
  }
  if (e > l + 1) {
    // 左闭右闭区间
    quickSort(A, l + 1, e)
  }
}

算法应用

leetcode

基于快排思想的快速选择

  1. 剑指 Offer 40. 最小的k个数
  2. 剑指 Offer II 076. 数组中的第 K 个最大元素