news 2026/6/26 3:14:55

树形选择排序的核心思想是通过构建一棵类锦标赛的二叉树结构,从叶子节点(原始数据)开始,两两比较

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
树形选择排序的核心思想是通过构建一棵类锦标赛的二叉树结构,从叶子节点(原始数据)开始,两两比较

树形选择排序的核心思想是通过构建一棵类锦标赛的二叉树结构,从叶子节点(原始数据)开始,两两比较,将较小者逐层向上传递,最终根节点即为最小关键字。例如在图 3-59(a) 中,所有待排序元素位于叶节点,内部节点保存每轮比较后的胜者(较小值),最终根节点得到全局最小值。当需要找出次小关键字时(如图 3-59(b) 所示),将已选出的最小值所在路径上的叶子节点设为无穷大或一个极大值,然后仅沿该路径向上重新调整树结构,无需重建整棵树,从而高效获得次小值。

败者树是对树形选择排序的优化,特别适用于多路归并排序场景(如外部排序中的 k 路归并)。与胜者树记录每轮比较的胜者不同,败者树的非叶子节点记录的是“败者”的归并段号。具体实现中,使用数组ls[]存储败者信息:ls[1]表示树根(最后的败者),而ls[0]特殊保留用于存放当前全局优胜者(即最小元素)所属的归并段号。每个叶子节点代表一个归并段的当前待比较元素。由于每次调整只需沿着父节点路径向上进行比较,无需访问兄弟节点,因此逻辑更清晰、代码实现更简洁,且维护效率更高。

这类树形结构的优势在于显著减少了比较次数——传统顺序查找最小值需 O(k) 次比较,而败者树仅需 O(log k) 次即可完成一轮选择,非常适合大规模数据在外存环境下的高效归并操作,广泛应用于数据库排序、文件系统处理和大数据分析等外部排序场景。

# 简化版败者树构建与调整示例(以4路归并为例)classLoserTree:def__init__(self,segments):self.k=len(segments)self.leaves=[float('inf')]*self.k# 各归并段当前元素foriinrange(self.k):ifsegments[i]:self.leaves[i]=segments[i].pop(0)self.ls=[-1]*self.k# ls[0..k-1],实际常扩展为大小为k+1self.winner=0# 初始优胜者索引self.build()defcompare(self,a,b):# 返回较小者的索引作为胜者,较大者的索引作为败者return(a,b)ifself.leaves[a]<=self.leaves[b]else(b,a)defadjust(self,idx):# 从叶子idx向上调整败者树t=(self.k+idx)//2whilet>0:ifself.ls[t]==-1orself.leaves[idx]>self.leaves[self.ls[t]]:idx,self.ls[t]=self.ls[t],idx t//=2self.winner=idxdefbuild(self):# 初始化败者树self.ls=[-1]*(self.k+1)# 使用1~k索引self.winner=0foriinrange(1,self.k+1):self.adjust(i)defget_min(self):min_val=self.leaves[self.winner]min_idx=self.winner# 更新该段新元素ifsegments[min_idx]:self.leaves[min_idx]=segments[min_idx].pop(0)else:self.leaves[min_idx]=float('inf')self.adjust(min_idx)returnmin_val

实现完整的败者树多路归并排序过程,需将多个已排序的子序列(归并段)通过败者树选出最小元素,依次写入输出序列,直到所有段的数据都被处理完毕。该过程包括:构建败者树、初始化各归并段数据、循环选取最小值并更新对应段元素、动态调整败者树。

以下是一个完整可运行的 Python 示例代码,演示如何使用败者树实现 4 路归并排序:

classLoserTreeMerge:def__init__(self,segments):""" 初始化败者树归并 :param segments: 多个已排序的列表组成的列表,如 [[1,4,7], [2,5,8], [3,6,9], [10,11]] """self.k=len(segments)# 深拷贝避免修改原数据self.segments=[seg[:]forseginsegments]# 叶子节点存储当前各段待比较元素self.leaves=[float('inf')]*self.kforiinrange(self.k):ifself.segments[i]:self.leaves[i]=self.segments[i].pop(0)# ls[0..k-1] 存储败者索引;ls[0] 特殊用于保存优胜者索引(根的父)self.ls=[-1]*self.k# 实际败者树数组大小为kself.winner_idx=-1# 当前全局最小值所在的段号self.build()defcompare_and_return_loser(self,a,b):""" 比较两个段的当前元素,返回败者(较大者)的索引 若相等,默认a胜 """ifself.leaves[a]<=self.leaves[b]:returnb# b 是败者else:returna# a 是败者defadjust(self,idx):""" 从叶子节点 idx 向上调整败者树 idx: 当前参与比较的段索引 """t=(idx+self.k)//2# 父节点位置(逻辑结构中)whilet>0:ifself.ls[t]==-1:# 初始空节点直接记录败者self.ls[t]=idxelse:loser=self.compare_and_return_loser(idx,self.ls[t])ifloser==idx:# 当前节点失败,保留原胜者,更新此层败者为idxpasselse:# 原败者失败,新败者是原来的胜者self.ls[t],idx=idx,self.ls[t]t//=2self.winner_idx=idx# 最终剩下的就是优胜者defbuild(self):""" 构建初始败者树 """# 初始化所有非叶节点为空self.ls=[-1]*self.k self.winner_idx=0# 对每个叶子进行一次调整foriinrange(self.k):self.adjust(i)defget_next_min(self):""" 获取当前最小元素,并推进对应归并段 """ifall(self.leaves[i]==float('inf')foriinrange(self.k)):returnNone# 所有段均已耗尽min_val=self.leaves[self.winner_idx]# 推进该段ifself.segments[self.winner_idx]:self.leaves[self.winner_idx]=self.segments[self.winner_idx].pop(0)else:self.leaves[self.winner_idx]=float('inf')# 重新调整败者树self.adjust(self.winner_idx)returnmin_valdefmerge_all(self):""" 执行完整多路归并,返回合并后的有序序列 """result=[]whileTrue:val=self.get_next_min()ifvalisNone:breakresult.append(val)returnresult# 示例使用if__name__=="__main__":segs=[[1,4,7,10],[2,5,8,11],[3,6,9,12],[13,14]]merger=LoserTreeMerge(segs)sorted_result=merger.merge_all()print("归并结果:",sorted_result)# 输出: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]

关键说明:

  • 时间复杂度:每轮选择最小值需 O(log k),共 n 个元素 → 总体 O(n log k),远优于朴素 O(nk)。
  • 空间复杂度:O(k),仅需存储败者树和当前各段首元素。
  • 适用性:特别适合外部排序场景,每次只需从磁盘读取一个块中的下一个元素。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/22 16:24:42

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

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

作者头像 李华
网站建设 2026/6/25 22:31:33

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

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

作者头像 李华
网站建设 2026/6/14 22:44:50

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

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

作者头像 李华
网站建设 2026/6/20 18:42:58

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

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

作者头像 李华
网站建设 2026/6/24 17:04:30

API文档撰写规范:清晰易懂地说明GLM-TTS接口用法

API文档撰写规范&#xff1a;清晰易懂地说明GLM-TTS接口用法 在智能语音应用日益普及的今天&#xff0c;用户不再满足于“能说话”的机器&#xff0c;而是期待更自然、有情感、个性化的语音交互体验。从虚拟主播到个性化有声书&#xff0c;从教育配音到多语言内容生成&#xff…

作者头像 李华