当前位置: 首页 > news >正文

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

树形选择排序的核心思想是通过构建一棵类锦标赛的二叉树结构,从叶子节点(原始数据)开始,两两比较,将较小者逐层向上传递,最终根节点即为最小关键字。例如在图 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),仅需存储败者树和当前各段首元素。
  • 适用性:特别适合外部排序场景,每次只需从磁盘读取一个块中的下一个元素。
http://www.jsqmd.com/news/194290/

相关文章:

  • 告别“点头眨眼”:一种采用手机屏幕发光方法的炫彩活体检测技术,为金融安全注入隐形盔甲
  • 医院管理大升级!双目摄像头成“智慧担当”
  • 2026口腔主治医师备考攻略分享:精研医术,赋能职业生涯新高度 - 医考机构品牌测评专家
  • 多机多卡部署推理加速学习路径
  • 2026口腔主治医师备考攻略分享:甄选核心干货,助您从容执笔答卷 - 医考机构品牌测评专家
  • 归并排序和基数排序是两种重要的排序算法,各自基于不同的思想实现高效、稳定的排序
  • ssm springboot动物园宠物动物救助领养商城之家网站全vue
  • 2026口腔主治医师考试机构推荐:多维视角下的深度测评 - 医考机构品牌测评专家
  • 从五孔探针到压力扫描阀:温特纳如何拿下风洞均匀性测试的核心难题
  • ssm springboot学生选修课 选课系统vue
  • 2026口腔主治医师考试机构推荐:深耕医学,赋能职业新高度 - 医考机构品牌测评专家
  • 2026五大口腔主治医师考试机构推荐指数排名 - 医考机构品牌测评专家
  • ssm springboot校园实习报告评分管理系统vue
  • 负能量的二分图
  • vue基于 SpringBoot 的会议室意见收集投票管理系统
  • 分享2026年口腔主治医师考试高效备考攻略 - 医考机构品牌测评专家
  • vue基于Java Web的物流快递管理系统的设计与实现
  • 跨设备状态同步实战:基于 HarmonyOS 分布式数据管理(DDM)构建多端协同应用 - 详解
  • 经济学专业背景求职者突破年龄限制的实战策略
  • RSYNC异地迁移备份工具
  • 2026年1月份国内环保涂料厂家汇总白皮书 - 一搜百应
  • python数据结构之链表
  • ErbB信号通路视角下的神经退行性病变研究
  • python数据结构之栈和队列
  • 整数倍抽取与整数倍内插分析与matlab仿真
  • 美团Java后端开发实习二面复盘:高并发、分布式系统与大模型应用深度连环问
  • 多机多卡消费级显卡实战
  • springboot养殖畜牧业养牛可视化大屏设计与实现vue
  • vue基于JAVA社区家政服务系统的设计与实现
  • 2026年 滑触线厂家权威推荐榜:C型/U型/M型/二型管/单极/多级/不锈钢/行车起重机专用,技术实力与安全耐用性深度解析 - 品牌企业推荐师(官方)