快速排序(Quick Sort)详解:从原理到实例

Source

快速排序(Quick Sort)详解:从原理到实例

快速排序是一种基于分治法的高效排序算法,平均时间复杂度为 O(n log n),是实际应用中最常用的排序算法之一。下面以经典的“左右指针法”为例,详细拆解它的完整工作流程。


前置知识:分治与基准数
  • 分治法:将大问题分解为小问题,解决小问题后合并结果。
  • 基准数(Pivot):每一轮排序选一个元素作为“标杆”,通过交换让比它小的数到左边,比它大的数到右边,最终基准数会到达它在有序数组中的正确位置。

快速排序的两大步骤
  1. 分区(Partition):选一个基准数,通过左右指针扫描和交换,把数组分成“左小右大”两部分,基准数归位。
  2. 递归排序:对基准数左边和右边的子数组重复“分区”操作,直到子数组长度为1或0。

分区操作的详细流程(左右指针法)

以数组 [5, 3, 8, 4, 2, 7, 1, 6] 为例,选第一个元素 5 作为基准数,演示分区过程:

步骤 操作 数组状态 说明
初始 左指针 left=0(指向5),右指针 right=7(指向6),基准数 pivot=5 [5, 3, 8, 4, 2, 7, 1, 6] 准备开始分区
1 右指针从右往左找小于5的元素:right=6(指向1) [5, 3, 8, 4, 2, 7, 1, 6] 1 < 5,停止左移
2 左指针从左往右找大于5的元素:left=2(指向8) [5, 3, 8, 4, 2, 7, 1, 6] 8 > 5,停止右移
3 交换 left=2right=6 的元素 [5, 3, 1, 4, 2, 7, 8, 6] 把小的1换到左边,大的8换到右边
4 右指针继续左移找小于5的元素:right=4(指向2) [5, 3, 1, 4, 2, 7, 8, 6] 2 < 5,停止左移
5 左指针继续右移找大于5的元素:left=4(指向2) [5, 3, 1, 4, 2, 7, 8, 6] 左右指针相遇,停止右移
6 交换基准数(索引0)和重合位置(索引4)的元素 [2, 3, 1, 4, 5, 7, 8, 6] 基准数5到达最终位置,左边都是<5的数,右边都是>5的数

递归排序子数组

分区后,数组被分成两部分:

  • 左子数组:[2, 3, 1, 4](都<5)
  • 右子数组:[7, 8, 6](都>5)

对这两个子数组重复“分区+递归”操作,直到所有子数组长度为1或0。

以左子数组 [2, 3, 1, 4] 为例:

  • 选基准数 2,分区后得到 [1, 2, 3, 4](2归位,左边[1],右边[3,4])
  • [3,4] 分区,选基准数 3,得到 [3,4](3归位,右边[4])

最终所有元素归位,排序完成。


快速排序的特点
  • 优点:平均时间复杂度 O(n log n),原地排序(空间复杂度 O(log n),递归栈开销),实际运行速度快。
  • 缺点:最坏时间复杂度 O(n²)(如数组已有序时,每次选的基准数都是最大/最小值),可通过“随机选基准数”或“三数取中”优化。

代码实现(Python)
  • 左右指针法(原地分区)
def quick_sort(arr, low=0, high=None):
    if high is None:
        high = len(arr) - 1
    if low >= high:
        return arr

    pivot = arr[low]
    left, right = low, high

    while left < right:
        while left < right and arr[right] >= pivot:
            right -= 1
        while left < right and arr[left] <= pivot:
            left += 1
        arr[left], arr[right] = arr[right], arr[left]

    arr[low], arr[right] = arr[right], arr[low]

    quick_sort(arr, low, right - 1)
    quick_sort(arr, right + 1, high)
    return arr

# 测试
arr = [5, 3, 8, 4, 2, 7, 1, 6]
print(quick_sort(arr))
  • 函数式分区法,遍历了两次 arr[1:]
def quick_sort(arr):
    if len(arr) <= 1:
        return arr
    pivot = arr[0]  # 选第一个元素为基准数
    left = [x for x in arr[1:] if x <= pivot]  # 小于等于基准数的放左边
    right = [x for x in arr[1:] if x > pivot]  # 大于基准数的放右边
    return quick_sort(left) + [pivot] + quick_sort(right)

# 测试
arr = [5, 3, 8, 4, 2, 7, 1, 6]
print(quick_sort(arr))  # 输出 [1, 2, 3, 4, 5, 6, 7, 8]