快速排序与归并排序 | AI生成和翻译

Home 2025.10

为什么快速排序让人感觉棘手(而归并排序不会)

你说得对——不参考资料直接手写快速排序就像在抓抹了油的猪,而归并排序则更像叠衣服:有条不紊且可预测。归并排序的”分治合”流程是线性且递归清晰的,合并步骤中没有任何意外。而快速排序是原地排序,依赖围绕”枢轴”(选定的分割点)交换元素的巧妙分区技巧。最初会感觉混乱,因为枢轴并不固定——更像是在游戏中不断被移动的裁判。但一旦领悟其精髓,就会感受到它优雅的效率(平均时间复杂度O(n log n),最坏情况下若枢轴选择不当则为O(n²))。

让我用一个自然的、故事化的视角介绍快速排序:想象按高度整理书架上杂乱堆放的书籍。你不是将书堆对半分开、逐本测量再合并(那是归并排序),而是选一本书作为”基准”(枢轴),然后重新排列其他书,使所有更矮的书位于其左侧,更高的书位于其右侧。枢轴最终会落在它的最终位置,你只需递归处理左右两个子书堆。无需额外空间——只需在书架上交换位置。这就像荷兰的”快速排序”升旗仪式(因此得名),将元素划分为三组:较矮组、基准组、较高组。

原理剖析:分区的魔力

快速排序之所以有效,在于带有保证的分治策略:每个分区步骤至少将一个元素(枢轴)放置在其正确的最终位置,每次至少缩小这么大规模的问题。最佳情况下,枢轴将数组均匀分割(如归并排序的对半分割),形成平衡的递归。最坏情况下(例如已排序数组搭配糟糕的枢轴选择),它会退化为O(n²),类似冒泡排序——但良好的枢轴选择策略使其在实践中速度极快。

关键洞见在于:分区强制执行不变性。一次分区后:

这保证了进展:递归树的深度平均最多为log n,每层总共进行O(n)次操作(扫描和交换)。

如何选择枢轴(以及为什么它在比较过程中会”移动”)

枢轴并非神圣不可移动——它只是你选择用来作为基准的任意元素。糟糕的选择(比如总是选第一个元素)可能导致失衡,以下是从简单到稳健的策略演进:

  1. 朴素策略:选择首元素(或尾元素)
    • 编码简单但有风险。在已排序数组[1,2,3,4,5]中,枢轴=1意味着左侧为空,右侧有4个元素——递归严重失衡。
    • “移动”原理:在分区过程中,你将其他所有元素与此枢轴值比较,但交换的是围绕其位置的元素。当边界跨越枢轴时,枢轴本身会被交换到正确位置。
  2. 改进策略:选择中间元素
    • 先将其临时交换至末尾,作为枢轴使用。直观上更平衡(更接近中位数),但仍可能受已排序/逆序输入的影响。
  3. 实践最佳:随机选择一个元素
    • 将其交换至末尾后进行分区。随机性平均掉了糟糕情况,使得最坏情况极不可能发生(以高概率保持O(n log n))。这是大多数库函数采用的方法。
  4. 进阶技巧(适用于面试):三数取中法
    • 选择首元素、中间元素、尾元素的中位数作为枢轴。计算快速,能规避常见陷阱。

在代码中,你通常通过先将枢轴交换至末尾来”固定”它,围绕其(而非位置)进行分区,最后再将其交换回归属位置。这就是为什么枢轴感觉在”移动”——它并非静止;分区过程通过两个相向跳跃的指针(左指针和右指针)动态地找到其位置,并交换违规元素。

动手示例:使用尾元素作为枢轴排序 [3, 7, 1, 9, 4]

让我们一步步演示分区过程。数组:[3, 7, 1, 9, 4]。枢轴 = 尾元素 = 4。(我们将根据需要交换其位置。)

逐步过程:

现在:4(索引2)的左侧是[3,1](均≤4,未排序),右侧是[9,7](均≥4,未排序)。枢轴=4已排序完成。递归处理左侧[3,1]和右侧[9,7]。

完全排序后:[1,3,4,7,9]。看到了吗?每一步都锁定进展,交换操作将枢轴”移动”到位。

伪代码概览(助你轻松实现)

quicksort(arr, low, high):
    若 low < high:
        pivot_idx = partition(arr, low, high)
        quicksort(arr, low, pivot_idx-1)
        quicksort(arr, pivot_idx+1, high)

partition(arr, low, high):  # Lomuto风格,枢轴在high
    pivot = arr[high]
    i = low - 1
    对于 j 从 low 到 high-1:
        若 arr[j] <= pivot:
            i += 1
            交换 arr[i] 与 arr[j]
    交换 arr[i+1] 与 arr[high]
    返回 i+1

“移动”发生在这些交换中:元素相互穿插移动,直至枢轴落定。用纸笔以5-6个元素练习——一旦理解分区,递归就会显得自然。若遇障碍,尝试在脑海中将其动画化为整理书架的过程。

深入探索:
快速排序可视化
CLRS 快速排序章节


Back

x-ai/grok-4-fast

Donate