news 2026/6/10 2:39:26

败者树的作用是优化多路归并排序中寻找最小元素的过程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
败者树的作用是优化多路归并排序中寻找最小元素的过程

败者树的作用是优化多路归并排序中寻找最小元素的过程。在 K 路归并中,传统方法需要每次比较 K 个归并段的当前记录以找出最小值,时间复杂度为 O(K),效率较低。而败者树通过构建一棵完全二叉树结构,将这一过程优化至 O(logK)。

  • 叶子节点:表示 K 个归并段当前待比较的记录,每个叶子对应一个归并段;
  • 内部节点:不存储胜者,而是记录“败者”——即在该轮比较中较大的记录所来自的归并段号;
  • 根节点的父节点 ls[0]:保存最终的“胜者”,即当前最小记录所属的归并段号。

算法流程详解(以 K=8 为例):

  1. 初始化阶段
    • 从每个归并段读取第一个记录存入数组b[1..K]
    • 构建初始败者树,所有内部节点初始化为“虚拟败者”K(防止越界),然后自底向上调整,确定最初的胜者和各层败者;
  2. Adjust(ls, i) 函数
    • 从第 i 个叶子节点(代表某个归并段的新记录)开始,沿路径向根部更新;
    • 每一层比较当前“参赛者”与原败者,胜者晋级参与上层比较,败者留在该节点;
    • 最终根节点的父节点ls[0]得到新的全局胜者;
  3. 归并主循环
    • 取出b[ls[0]]对应的记录输出到结果序列;
    • 调用Get_nextRec(ls[0])从该归并段读取下一条记录;
    • 若该段未空(非 MAXKEY),则将其作为新参赛者调用Adjust(ls, ls[0])更新败者树;
    • 若已空,则可用特殊标记处理或停止参与后续比较;
    • 重复直至所有归并段均为空;

关键优势分析:

  • 高效性:每次替换仅需 O(logK) 时间完成调整,显著优于朴素 O(K) 扫描;
  • 空间节省:败者树仅需 K−1 个内部节点(数组ls[0..K−1]),结构紧凑;
  • 可扩展性强:适用于大规模外部排序场景下的多路平衡归并;

边界控制机制:

  • 使用MINKEY表示无穷小,用于初始化;
  • 使用MAXKEY表示无穷大,当某归并段耗尽时返回此值,确保其不再参与有效竞争;

综上所述,败者树是一种专为多路归并设计的高效选择结构,核心在于“记录败者、传播胜者”的思想,极大提升了外部排序的整体性能。
Adjust(ls, i)是败者树的核心调整函数,其作用是从第i个叶子节点(即第i个归并段的新记录)开始,沿着从叶子到根的路径重新进行比赛,更新各层的“败者”,最终确定新的全局胜者,并将其存入ls[0]

✅ 假设前提:

  • 败者树是一棵完全二叉树,共有K个叶子节点(对应 K 路归并),K为 2 的幂;
  • 内部节点存储的是“败者”的归并段号(即较大的记录所在段号);
  • 根节点的父节点ls[0]存储当前胜者(最小记录所在的段号);
  • 叶子节点数据保存在数组b[1..K]中,b[i]表示第i段当前参与比较的记录关键字;
  • ls[1..K-1]存储败者树的内部节点(共 K−1 个);

📌 Adjust(ls, i) 实现逻辑(伪代码 + 解释)

voidAdjust(intls[],inti,intb[],intK){// s 表示当前正在上升的比赛节点(从叶子 i 开始)intt=0;// 当前层级对应的内部节点索引:t ∈ [K-1, K/2, ..., 1]intwinner=i;// 当前参赛的“胜者”段号(初始为 i)// 从叶子向上遍历每一层内部节点,直到根部for(intlevel=0;(1<<level)<K;level++){t=(K+winner)/2;// 父节点在 ls 中的索引(完全二叉树性质)if(ls[t]==K){// 初始化状态:该节点无有效败者,winner 直接晋级ls[t]=winner;winner=i;// 注意:这里应保持 winner 不变?需修正逻辑}else{// 比较当前 winner 与原 ls[t] 所代表的败者if(b[winner]<=b[ls[t]]){// winner 更小,继续晋级,原 ls[t] 成为新败者inttemp=ls[t];ls[t]=winner;winner=temp;}// 否则:原 ls[t] 更小,它继续晋级,winner 成为败者留在 ls[t]}// 继续下一轮比较,直到到达根节点上方}// 最终 winner 是全局最小者,存入 ls[0]ls[0]=winner;}

⚠️ 上述伪代码存在细节问题。更准确的做法如下:


✅ 正确实现方式(标准教科书版本):

voidAdjust(intls[],inti,intb[],intK){intt=(K+i)/2;// 当前比较层级的父节点索引while(t>0){// 比较当前参赛者 i 与 ls[t] 记录的旧败者if(b[i]>b[ls[t]]){// i 是败者,保留胜者 ls[t] 继续上行,i 下降到该层成为败者inttemp=i;i=ls[t];// 新参赛者是原来的胜者ls[t]=temp;// 当前败者记录下来}// 否则 i 是胜者,直接上行,败者仍为 ls[t]t/=2;// 移动到上一层父节点}// 最终 i 是胜者,记录在 ls[0]ls[0]=i;}

🔍 详细步骤说明(以 K=8,i=3 为例):

  1. 初始:b[3]更新了新记录,需重新调整。
  2. t = (8+3)/2 = 5→ 第一层父节点ls[5]
  3. 比较b[3]b[ls[5]]
    • b[3] > b[ls[5]],则3是败者,写入ls[5],原来ls[5]的值继续作为“胜者”参与上层;
    • 否则ls[5]仍是败者,3继续上行;
  4. t = 5/2 = 2ls[2],重复比较;
  5. t = 2/2 = 1ls[1],最后比较;
  6. t = 1/2 = 0结束,将最终胜者存入ls[0]

🎯 关键思想总结:

  • 只记录败者:每个内部节点保存的是在这次比赛中输掉的一方;
  • 胜者持续向上挑战:确保根部ls[0]总是当前最小元素来源;
  • 时间复杂度 O(logK):每轮向上走 log₂K 层,每层一次比较;
  • 空间效率高:仅用 K−1 个节点即可维护整个选择结构;

✅ 示例调用场景:

// 输出最小元素后,从第 i 段读取下一个记录b[i]=Get_nextRec(i);if(b[i]!=MAXKEY){Adjust(ls,i,b,K);// 重新调整败者树}else{// 归并段已空,可特殊处理(如不再参与)}

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/9 22:45:59

基于Actor-Critic(A2C)强化学习RL的四旋翼无人机UAV悬停控制

基于Actor-Critic(A2C)强化学习RL的四旋翼无人机UAV悬停控制 简介&#xff1a;该代码训练了一个优势演员-评论家(A2C)强化学习代理&#xff0c;以控制四旋翼飞行器的电机速度&#xff0c;使其在随机角加速度扰动作用于控制轴&#xff08;俯仰、横滚和偏航&#xff09;的情况下保…

作者头像 李华
网站建设 2026/6/9 3:33:58

vue基于JAVA社区家政服务系统的设计与实现

目录 摘要 开发技术 核心代码参考示例1.建立用户稀疏矩阵&#xff0c;用于用户相似度计算【相似度矩阵】2.计算目标用户与其他用户的相似度总结源码文档获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01; 摘要 随着社会发展和生活节奏加快&#x…

作者头像 李华
网站建设 2026/6/9 20:07:49

中专模具生进大厂攻略:3类核心证书,逆袭2026

证书战略&#xff1a;构建通往大厂的“能力金三角”✅专业基本功扎实✅掌握先进制造技术✅具备持续改进的潜力&#x1f4d0; 一、进大厂必备的8类高价值证书1. 计算机辅助设计&#xff08;CAD&#xff09;绘图员&#xff08;中级&#xff09;二维设计的底线&#xff1a;大厂所有…

作者头像 李华
网站建设 2026/6/9 18:44:02

免费试用+增值服务模式:吸引用户购买GPU计算资源

免费试用增值服务模式&#xff1a;吸引用户购买GPU计算资源 在AI语音技术飞速发展的今天&#xff0c;我们已经不再满足于“能说话”的机器。从智能客服到有声读物&#xff0c;从虚拟主播到个性化语音助手&#xff0c;市场对语音合成&#xff08;TTS&#xff09;的要求早已超越基…

作者头像 李华
网站建设 2026/6/9 18:35:15

app.py入口文件分析:理解GLM-TTS Web服务运行机制

GLM-TTS Web服务运行机制解析&#xff1a;从app.py看AI语音系统的工程化落地 在生成式AI迅猛发展的今天&#xff0c;语音合成技术早已不再局限于实验室中的“能说会道”&#xff0c;而是朝着个性化、情感化和即用化的方向快速演进。尤其是零样本语音克隆&#xff08;Zero-shot …

作者头像 李华