快速排序(Quicksort)

217 阅读2分钟

快速排序(Quicksort)是一种高效的排序算法,采用了分治法(Divide and Conquer)策略来把一个序列分为较小和较大的两个子序列,然后递归地排序两个子序列。

快速排序的基本步骤

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

快速排序的伪代码

plaintext
function quicksort(array)
    if length(array) ≤ 1
        return array
    pivotIndex ← choosePivot(array)
    pivot ← array[pivotIndex]
    swap pivot with the last element of the array
    storeIndex ← first element of the array
    for i from first to second last element
        if array[i] < pivot
            swap element at i with element at storeIndex
            increment storeIndex
    swap pivot with the element at storeIndex
    leftSubArray ← subarray of elements before storeIndex
    rightSubArray ← subarray of elements after storeIndex
    return concatenate(quicksort(leftSubArray), pivot, quicksort(rightSubArray))

快速排序的 JavaScript 实现

以下是一个简单的快速排序的 JavaScript 实现:

javascript
function quickSort(arr, left = 0, right = arr.length - 1) {
  if (left < right) {
    const partitionIndex = partition(arr, left, right);
    quickSort(arr, left, partitionIndex - 1);
    quickSort(arr, partitionIndex + 1, right);
  }
  return arr;
}

function partition(arr, left, right) {
  const pivot = arr[right]; // 选择最后一个元素作为基准
  let i = left - 1; // i 用来标记小于基准的元素的最后一个位置

  for (let j = left; j < right; j++) {
    if (arr[j] < pivot) {
      i++;
      [arr[i], arr[j]] = [arr[j], arr[i]]; // 交换元素
    }
  }

  [arr[i + 1], arr[right]] = [arr[right], arr[i + 1]]; // 把基准元素放到中间位置
  return i + 1; // 返回基准元素的位置
}

// 测试
const unsortedArray = [3, 6, 8, 10, 1, 2, 1];
console.log("Unsorted:", unsortedArray);
const sortedArray = quickSort(unsortedArray);
console.log("Sorted:", sortedArray);

时间复杂度

  • 最好情况:O(n log n),当每次都能均匀分割数组时。
  • 平均情况:O(n log n),这是快速排序最常见的情况。
  • 最坏情况:O(n^2),当输入数组已经是有序的或者是逆序的,并且每次都选择第一个或最后一个元素作为基准时。

空间复杂度

快速排序的空间复杂度为 O(log n),这是由于递归调用栈的深度决定的。

选择基准的策略

选择基准的策略会影响到快速排序的效率。常见的选择方法有:

  • 选择第一个元素;
  • 选择最后一个元素;
  • 随机选择;
  • 选择中位数。

随机选择基准可以减少最坏情况的发生概率,而选择中位数作为基准可以尽量保证每次划分的平衡性,从而接近最优情况的时间复杂度。

快速排序因其高效和简洁成为了许多场景下首选的排序算法。