043快速选择
2026/8/5 9:48:42 网站建设 项目流程

快速选择 - 平均O(n)找第K小元素

043快速排序:征服世界的算法

📰 5W1H 发明者故事

Who(何人)- 发明者是谁?

发明者:托尼·霍尔(C.A.R. Hoare,全名 Sir Charles Antony Richard Hoare)
背景:霍尔是英国计算机科学家,牛津大学教授,1980年图灵奖得主。他以发明快速排序(Quicksort,1959-1960)和形式化验证方法(霍尔逻辑)著称。快速选择(Quickselect)是他在研究快速排序过程中同时发现的,作为partition操作的一个直接应用。

当时的处境:1960-1961年,霍尔在苏联进修机器翻译期间,独立发现了快速排序算法。回到英国后,他在Elliott Brothers公司工作期间系统化了这些想法,并意识到快速排序的partition步骤本身就能回答"第K小是什么"这一问题,而无需完整排序。

When(何时)- 什么时候发明的?

时间:1961年,与快速排序同期发表于《ACM通讯》第4卷第7期
时代背景

  • 快速排序1959年由霍尔在莫斯科构思,1961年正式发表
  • 计算机时间极为昂贵,任何能减少计算量的算法都有巨大价值
  • 统计学对"找中位数"有强烈需求(稳健统计、噪声过滤)
  • 算法分析(复杂度理论)开始成为独立学科

Where(何地)- 在哪里发明的?

地点:英国伦敦,Elliott Brothers计算机公司
环境:霍尔在Elliott Brothers担任程序员时,需要为公司的计算机实现高效的排序和选择算法。他在一台Elliott 803计算机上实现并测试了这些算法,这台计算机使用纸带输入,内存只有几千个字。

What(何事)- 发明了什么?

算法:快速选择(Quickselect)
核心概念:利用快速排序的partition操作,将数组分为"小于基准"、“基准”、"大于基准"三部分,根据K与基准位置的关系,只递归处理其中一部分(而非两部分),平均时间O(n)
关键变体

  • 基础Quickselect:随机选择基准,期望O(n)时间,最坏O(n²)
  • 中位数的中位数(Median of Medians):Floyd-Rivest等人1973年提出,保证最坏O(n),但常数因子较大

Why(何因)- 为什么发明?

要解决的问题

  1. 中位数计算:统计中的中位数计算如果先完整排序需要O(n log n),实际只需O(n)
  2. Top-K问题:找前K大元素,不需要完整排序
  3. 顺序统计量:任意百分位数(如第75百分位)的高效计算
  4. 算法正确性:快速排序完成后,任意位置元素都已在最终正确位置,Quickselect只需找到K位置时停止

当时的挑战

  • 随机化选择基准的方法在当时尚未普及,最坏情况O(n²)是真实风险
  • 如何向用户保证"平均"O(n)而非"最坏"O(n²)
  • 中位数的中位数算法虽然理论最优,但实现复杂,实践中常数因子大

动机:霍尔的核心洞察是:要找第K小的元素,不需要知道其他元素的顺序。Partition操作告诉我们基准的精确排名,如果基准恰好排在第K位,我们就找到了答案;否则只需在更小的一半中继续寻找。每次期望将问题规模减半,总期望工作量是O(n+n/2+n/4+…)=O(2n)=O(n)。

How(何果)- 如何实现?有什么影响?

实现思路(Quickselect)

  1. 若数组长度为1,返回唯一元素
  2. 选择一个基准(pivot),执行partition:将数组分为[小于pivot] [pivot] [大于pivot]
  3. 设基准的下标为p:若p==k-1,返回pivot;若p>k-1,在左半段找第k小;否则在右半段找第k-p-1小

技术方案(Median of Medians保证最坏O(n))

将n个元素分为n/5组,每组5个 对每组做插入排序,找到中位数 对所有组的中位数递归找中位数(即"中位数的中位数") 用这个中位数作为pivot执行partition 保证pivot排名在[n/4, 3n/4]之间,递归规模至多3n/4 T(n) = T(n/5) + T(3n/4) + O(n) = O(n)

历史影响

  • Quickselect是实践中最常用的选择算法,出现在几乎所有标准库中
  • 中位数的中位数(Blum等人,1973)是理论计算机科学的里程碑,证明了选择问题的线性下界
  • C++标准库的nth_element()函数使用Introselect(结合Quickselect和Median of Medians)
  • 机器学习中的K近邻算法、决策树分裂点计算都用到快速选择
  • 计算几何中的随机增量算法大量借用Quickselect的框架

今天的使用

  • 数据库的ORDER BY LIMIT K查询优化
  • 图像处理中的中位数滤波(去噪)
  • 统计分析中的百分位数计算
  • 机器学习特征选择(找最重要的K个特征)

📝 自然语言需求定义

需求名称:实现快速选择算法,包含基础Quickselect(期望O(n))和中位数的中位数(最坏O(n)保证)

功能需求(用精确的中文描述)

  1. 快速选择(Quickselect):找数组中第k小的元素(k从1开始)

    • 输入:整数数组、长度n、k(1<=k<=n)
    • 操作:随机选基准,partition后根据基准位置决定递归左段还是右段
    • 输出:第k小的元素值(不修改原数组,使用副本)
  2. 中位数的中位数(Median of Medians):最坏情况O(n)的选择算法

    • 输入:整数数组、长度n、k(1<=k<=n)
    • 操作:将数组分为每组5个,找每组中位数,递归找这些中位数的中位数,用它作pivot
    • 输出:第k小的元素值,最坏情况O(n)保证

约束条件

  • k的范围:1<=k<=n(1表示最小值,n表示最大值)
  • 不修改原数组(内部使用副本操作)
  • Quickselect期望O(n),最坏O(n²)
  • Median of Medians最坏O(n),但常数因子约为Quickselect的5倍

验收标准(必须可验证)

编号测试场景(自然语言描述)预期结果验证方式
1对[3,1,4,1,5,9,2,6]找第1小(最小值)1与min()函数结果对比
2对[3,1,4,1,5,9,2,6]找第8小(最大值)9与max()函数结果对比
3对[3,1,4,1,5,9,2,6]找第4小(中位数附近)3先排序再取第4个验证
4对[7,7,7,7,7]找任意第k小7无论k值如何,结果均为7
5用中位数的中位数对[3,1,4,1,5,9,2,6]找第4小与Quickselect结果相同两种方法结果一致
6大数组:对1000个随机数找第500小与排序后取第500个结果相同先排序取值,再用quickselect验证
7各种k值(1,2,n/2,n-1,n)均正确与暴力排序结果一致排序后取对应下标比较

AI 生成提示

基于以上需求和验收标准,用标准C语言实现快速选择和中位数的中位数算法。 要求: 1. 使用标准C99,gcc -Wall无警告 2. quickselect(arr, n, k)不修改原数组(内部复制),返回第k小的值 3. median_of_medians(arr, n, k)同上,使用中位数的中位数作pivot 4. partition(arr, left, right, pivot_idx)返回基准的最终位置 5. insertion_sort_small(arr, n)用于对小组(5个)排序 6. 完整内存管理:malloc/free配对 7. 代码必须有详细中文注释,解释为什么MoM保证最坏O(n) 8. 测试框架使用 tests_passed/tests_failed 计数器 9. main返回 tests_failed > 0 ? 1 : 0 核心函数: - partition(arr, left, right, pivot_idx) - 以指定下标为基准partition - quickselect(arr, n, k) - 期望O(n)选择 - median_of_medians(arr, n, k) - 最坏O(n)选择 - is_sorted(arr, n) - 有序性检验(用于验收测试辅助)

💻 C语言实现文件

对应文件:quickselect.c

编译运行:

gcc-std=c99-Wall-oquickselect_test quickselect.c ./quickselect_test

核心函数:

  • partition(arr, left, right, pivot_idx)- partition操作
  • quickselect(arr, n, k)- 期望O(n)快速选择
  • median_of_medians(arr, n, k)- 最坏O(n)保证的选择算法

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询