图解题库 / 排序 · 快排

快速排序

中等 含交互动画

学完这道你应该能: 说清它为什么用「快排」,而不是死记步骤; 合上页面,自己默写出核心代码; 用 30 秒把思路讲清楚。

题目描述

选基准 pivot → partition 把数组分成「<pivot | pivot | ≥pivot」→ 对左右两段递归。

输入 = [5, 2, 8, 1, 9, 3]
输出 = [1, 2, 3, 5, 8, 9]

思路解析

取最后一个数 3 当基准。用一个边界 i 指"小区的末尾"。扫描其余元素:遇到比基准小的,就把它换到小区里(i 前进)。扫完,把基准换到小区后面——它左边全 <3、右边全 ≥3,基准归位

选基准 = 3 (最后一个):基准 pivot = 3(下标 5,橙色)。开始扫描前面的元素,把小于 3 的归到左边。

遇到 2 < 3 · 换入左区:扫到 2 < 3,把它换到左区(和当前左区末尾交换)。左区现在 = [2]。

遇到 1 < 3 · 换入左区:8 不小于 3 跳过;扫到 1 < 3,换进左区。左区 = [2,1]。9 也不小,跳过。

基准归位 · 3 放到左区后面:扫描结束,把基准 3 换到左区后面(下标 2)。现在 3 已归位:左边 [2,1] 全 <3、右边 [5,9,8] 全 ≥3。

左半 partition · 基准取 1:对左半 [2,1] 做同样的 partition:基准取 1。扫描 2 不比 1 小,所以基准 1 直接归位到最前。递归就是"在子数组上重复一模一样的过程"。

递归左半完成 → [1,2]:左半排成 [1,2],左边整段(含已归位的基准 3)全部有序。

递归右半 [5,9,8] → [5,8,9]:对右半 [5,9,8] 同样递归,排成 [5,8,9]。两半都有序,整体 [1,2,3,5,8,9] 完成。

快排的灵魂是 partition——每趟让基准"一步到位",并把问题切成两个独立子问题。"找第 K 大(快速选择)"就是只递归其中一半。

参考代码(Python)

Python
1def quicksort(a, lo, hi):
2    if lo >= hi: return
3    pivot = a[hi]; i = lo - 1            # i: 小区末尾
4    for j in range(lo, hi):
5        if a[j] < pivot:                # 比基准小
6            i += 1; a[i], a[j] = a[j], a[i]
7    a[i+1], a[hi] = a[hi], a[i+1]       # 基准归位
8    quicksort(a, lo, i); quicksort(a, i+2, hi)   # 递归两半

复杂度分析

  • 时间复杂度:平均 O(n log n) —— 最坏 O(n²)(每次划分极不均)
  • 空间复杂度:O(log n) —— 递归栈

套路模板

记住骨架:基准取末位、i 守小区边界、j 扫描遇小就换、最后基准归位返回其下标。快速选择、三路快排都从它变化。

Python
1def partition(a, lo, hi):
2    pivot, i = a[hi], lo - 1
3    for j in range(lo, hi):
4        if a[j] < pivot:                # 小的换进左区
5            i += 1; a[i], a[j] = a[j], a[i]
6    a[i+1], a[hi] = a[hi], a[i+1]      # 基准归位
7    return i + 1                       # 基准最终下标

易错点

  • 基准固定取首/尾遇有序退化 → ✅ 随机选基准或三数取中(已排序数据下固定基准会 O(n²))
  • 递归区间含基准本身 → ✅ 递归 [lo,i] 和 [i+2,hi](基准已归位,不该再参与划分)

以上文字与上方动画完全同一思路:先看动画建立直觉 → 读文字巩固 → 关掉页面自己默写一遍代码,能写出来才算真的掌握

下一题 →归并排序 ← 返回题库