news 2026/3/21 21:28:08

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

作者头像

张小明

前端开发工程师

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/3/15 1:42:02

经济学专业背景求职者突破年龄限制的实战策略

一、精准定位&#xff1a;年龄限制背后的真实职场需求与技能补充经济学专业背景的求职者在面对年龄壁垒时&#xff0c;可考虑通过补充人工智能等前沿技能&#xff0c;增强自身复合竞争力。当前市场对既懂经济分析又掌握AI应用能力的复合型人才需求显著增加。经济学AI的复合优势…

作者头像 李华
网站建设 2026/3/21 10:36:01

vue航空航天太空科普网站 可视化大屏改_2dhz0

目录Vue航空航天科普网站的可视化大屏设计核心功能模块设计技术实现方案交互体验优化开发技术核心代码参考示例1.建立用户稀疏矩阵&#xff0c;用于用户相似度计算【相似度矩阵】2.计算目标用户与其他用户的相似度总结源码文档获取/同行可拿货,招校园代理 &#xff1a;文章底部…

作者头像 李华
网站建设 2026/3/19 6:31:07

C++学习记录-旧题新做-分割链表

旧题链接&#xff1a;https://blog.csdn.net/chamao_/article/details/143628470?fromshareblogdetail&sharetypeblogdetail&sharerId143628470&sharereferPC&sharesourcechamao_&sharefromfrom_link C解法&#xff1a; /*** Definition for singly-lin…

作者头像 李华
网站建设 2026/3/16 2:56:38

学长亲荐!8款AI论文写作软件测评,研究生开题报告必备

学长亲荐&#xff01;8款AI论文写作软件测评&#xff0c;研究生开题报告必备 学术写作工具测评&#xff1a;2026年研究生必备推荐 随着AI技术的不断进步&#xff0c;越来越多的研究生开始依赖AI论文写作软件来提升科研效率。然而&#xff0c;面对市场上种类繁多的工具&#xff…

作者头像 李华
网站建设 2026/3/15 13:33:28

博物馆解说系统升级:用GLM-TTS替代传统录音

博物馆解说系统升级&#xff1a;用GLM-TTS替代传统录音 在一座大型历史博物馆里&#xff0c;策展团队临时决定更换一件珍贵文物的说明文字。按照惯例&#xff0c;这意味着要重新联系播音员、预约录音棚、剪辑音频、上传到导览系统——整个流程至少三天起步。但这次&#xff0c…

作者头像 李华
网站建设 2026/3/19 14:56:15

PHP的$_SESSION的庖丁解牛

$_SESSION 是 PHP 提供的 服务端会话管理机制&#xff0c;用于在无状态的 HTTP 协议上模拟用户状态。 它看似简单&#xff0c;但涉及 存储机制、安全边界、生命周期、分布式挑战 四重工程细节。 错误使用会导致 会话劫持、状态污染、内存泄漏、扩展性瓶颈。一、机制原理&#x…

作者头像 李华