【16】数据结构之基于树的排序算法篇章
目录标题
- 选择排序
- 简单选择排序
- 树形选择排序
- 堆排序
- 堆的定义Heap
- 小跟堆
- 大根堆
- 堆的存储
- 堆的代码设计
- 堆排序的代码设计
- 排序算法综合比较
选择排序
- 基本思想:从待排序的序列中选出最大值或最小值,交换该元素与待排序序列的头部元素,对剩下的元素重复操作,直到完成所有元素排序.
简单选择排序
- 第i次排序通过n-i次关键字的比较,从n-i+1个元素中选出关键字最小的元素,并和第i个元素交换.共需进行i-1次比较,直到所有元素排序完成为止.
- 示意图

- 代码实现与调试
# 树的排序--简单选择排序
class SelectSort(object):def __init__(self, items):# 待排序的序列self.items = itemsdef selectSort(self):"""简单选择排序:return:"""# 共n轮排序for i in range(len(self.items)):# 待交换的元素index = i# 在未排序的序列中选取最小的元素for j in range(i+1, len(self.items)):if self.items[j] < self.items[index]:index = j# 最小的元素不是带交换的元素,则两者交换if index != i:self.items[i],self.items[index] = self.items[index],self.items[i]if __name__ == "__main__":arr = [84, 62, 35, 77, 55, 14, 35, 98]select = SelectSort(arr)select.selectSort()print(arr)
树形选择排序
- 树形选择排序也称锦标赛排序.
- 首先所有参加比赛的选手两两分组,每组产生一个胜利者,然后这些胜利者再两两分组进行比赛,每组产生一个胜利者,之后重复执行,直到最后只有一个胜利者为止.
- 示意图

- 代码实现与调试
class TournamentSort:def __init__(self, arr):self.original = arr.copy()self.n = len(arr)# 初始化所有属性,确保空数组时属性存在self.leaf_size = 0self.tree_size = 0self.tree = []if self.n == 0:return # 空数组直接返回# 计算扩展到下一个2的幂次方的叶子数量self.leaf_size = 1 << (self.n - 1).bit_length()self.tree_size = 2 * self.leaf_size - 1# 初始化树结构并用inf填充空位self.tree = [float('inf')] * self.tree_size# 将原始数据填充到叶子节点self.tree[-self.leaf_size: -self.leaf_size + self.n] = self.original# 构建初始锦标赛树(自底向上)for i in range(self.tree_size - 1, 0, -1):if i % 2 == 1: # 只处理左子节点,避免重复计算parent = (i - 1) // 2self.tree[parent] = min(self.tree[i], self.tree[i + 1])def get_min(self):"""获取当前最小值并重构树"""if self.n <= 0:return Nonewinner = self.tree[0]# 查找叶子层中的最小值位置idx = self.tree_size // 2 # 叶子层起始索引while idx < self.tree_size:if self.tree[idx] == winner:breakidx += 1# 标记该位置为已选中self.tree[idx] = float('inf')self.n -= 1# 自底向上更新树结构while idx > 0:parent = (idx - 1) // 2sibling = idx + 1 if idx % 2 == 1 else idx - 1self.tree[parent] = min(self.tree[idx], self.tree[sibling])idx = parentreturn winnerdef sort(self):"""执行完整排序过程"""sorted_arr = []while True:val = self.get_min()if val is None:breaksorted_arr.append(val)return sorted_arrdef print_tree(self):"""可视化打印树结构(调试用)"""print("当前锦标赛树结构:")if self.tree_size == 0:print("空树")returnlevel = 0level_size = 1while level_size <= self.tree_size:start = 2 ** level - 1end = start + level_sizeprint(f"Level {level}: {self.tree[start:end]}")level += 1level_size *= 2# ---------------------- 测试用例 ----------------------
if __name__ == "__main__":test_cases = [[3, 1, 4, 1, 5, 9, 2, 6], # 常规测试[9, 3, 5, 2, 8], # 奇数元素[5, 3, 8, 6, 2], # 重复值测试[1], # 单个元素[] # 空数组]for i, case in enumerate(test_cases):print(f"\n测试用例 {i + 1}: {case}")ts = TournamentSort(case)ts.print_tree() # 调试查看初始树结构sorted_result = ts.sort()print(f"排序结果: {sorted_result}")print("验证结果:", "正确" if sorted_result == sorted(case) else "错误")
堆排序
- 对树形选择排序的一种改进
堆的定义Heap
- 堆是二叉树的一种
- 堆是完全二叉树
- 堆中任意结点的值总是不大于或者不小于其双亲结点的值
- 堆分为大根堆和小跟堆
小跟堆
- 如果根结点存在左孩子结点,则根结点的值小于或等于左孩子结点的值
- 如果根结点存在右孩子结点,则根结点的值小于或等于右孩子结点的值
- 根结点的左右子树也是小跟堆
- 小跟堆示意图

大根堆
- 如果根结点存在左孩子结点,则根结点的值大于或等于左孩子结点的值
- 如果根结点存在右孩子结点,则根结点的值大于或等于右孩子结点的值
- 根结点的左右子树也是大跟堆
- 大跟堆示意图

堆的存储
- 常用顺序结构进行存储.
- 重建堆方法
- 首先将完全二叉树根结点中的元素移出,
- 从空结点的左右孩子结点中选出一个关键字较小的元素,上移到空结点中,
- 当前那个较小关键字较小的子结点相当于空结点,
- 重复上述移动原则
- 直到空结点的左右孩子结点的关键字均不小于待调整元素的关键字为止
- 建立初始堆算法思路
- 一个任意序列可以看成对应的完全二叉树,由于叶子结点可以视为单元素的堆,然后反复利用重建堆方法,自底向上逐层把所有子树调整为堆,直到将整个完全二叉树调整为堆为止
堆的代码设计
class Heap:def __init__(self, items=[]):self.items = items.copy()self.build_min_heap()def build_min_heap(self):"""将列表初始化为小根堆"""length = len(self.items)for i in range(length // 2 - 1, -1, -1):self._sift_down(i, length)def insert(self, key):"""插入新元素并上浮调整"""self.items.append(key)self._sift_up(len(self.items) - 1)def delete(self):"""删除堆顶元素"""if not self.items:raise IndexError("堆为空,无法删除")# 将最后一个元素移到堆顶removed = self.items[0]self.items[0] = self.items[-1]self.items.pop()# 下沉调整if self.items:self._sift_down(0, len(self.items))return removeddef _sift_up(self, index):"""元素上浮操作"""parent = (index - 1) // 2while parent >= 0 and self.items[index] < self.items[parent]:self.items[index], self.items[parent] = self.items[parent], self.items[index]index = parentparent = (index - 1) // 2def _sift_down(self, index, size):"""元素下沉操作"""smallest = indexleft = 2 * index + 1right = 2 * index + 2if left < size and self.items[left] < self.items[smallest]:smallest = leftif right < size and self.items[right] < self.items[smallest]:smallest = rightif smallest != index:self.items[index], self.items[smallest] = self.items[smallest], self.items[index]self._sift_down(smallest, size)def __str__(self):return str(self.items)# ---------------------- 测试用例 ----------------------
if __name__ == "__main__":# 测试初始化与插入删除heap = Heap([10, 25, 15, 40, 25, 20, 30, 50, 55])print("初始堆:", heap) # 输出: [10, 25, 15, 40, 25, 20, 30, 50, 55]heap.insert(9)print("插入9后:", heap) # 输出: [9, 25, 10, 40, 55, 15, 30, 50, 25, 20]val = heap.delete()print(f"删除元素 {val} 后:", heap) # 删除9后:[10, 25, 15, 40, 55, 20, 30, 50, 25]val = heap.delete()print(f"删除元素 {val} 后:", heap) # 删除10后:[15, 25, 20, 40, 25, 55, 30, 50]# 测试空堆empty_heap = Heap()try:empty_heap.delete()except IndexError as e:print("空堆删除测试:", e) # 输出:堆为空,无法删除# 测试单元素堆single_heap = Heap([5])single_heap.delete()print("单元素堆删除后:", single_heap) # 输出:[]
堆排序的代码设计
class HeapSort:def __init__(self, items):self.items = items # 初始化待排序数组def heapSort(self):"""堆排序主方法"""length = len(self.items)# 1. 构建最大堆(从最后一个非叶子节点开始调整)for i in range(length // 2 - 1, -1, -1):self._adjust_max_heap(self.items, i, length)# 2. 排序阶段(依次将堆顶元素移到末尾)for i in range(length - 1, 0, -1):# 交换堆顶(最大值)与当前末尾元素self.items[0], self.items[i] = self.items[i], self.items[0]# 调整剩余堆结构(堆大小逐渐减小)self._adjust_max_heap(self.items, 0, i)def _adjust_max_heap(self, arr, root, heap_size):"""调整最大堆(递归实现)"""largest = root # 初始化最大值为根节点left = 2 * root + 1 # 左子节点索引right = 2 * root + 2 # 右子节点索引# 比较左子节点if left < heap_size and arr[left] > arr[largest]:largest = left# 比较右子节点if right < heap_size and arr[right] > arr[largest]:largest = right# 如果最大值位置变化,交换并递归调整子树if largest != root:arr[root], arr[largest] = arr[largest], arr[root]self._adjust_max_heap(arr, largest, heap_size)# ---------------------- 测试用例 ----------------------
if __name__ == "__main__":nums = [40, 55, 73, 12, 98, 27]sorter = HeapSort(nums)sorter.heapSort()print("排序结果:", nums) # 输出: [12, 27, 40, 55, 73, 98]
排序算法综合比较

相关文章:
【16】数据结构之基于树的排序算法篇章
目录标题 选择排序简单选择排序树形选择排序 堆排序堆的定义Heap小跟堆大根堆堆的存储堆的代码设计堆排序的代码设计 排序算法综合比较 选择排序 基本思想:从待排序的序列中选出最大值或最小值,交换该元素与待排序序列的头部元素,对剩下的元…...
华熙生物亮相消博会,这次又带来了什么样的变化?
首先,从展示层面来看,华熙生物在消博会上构建科技桥梁,展台主视觉展示糖生物学发展历程与自身发展交织历程,这象征着中国生物科技企业从产业突围到定义全球标准的蜕变。这一展示不仅提升了华熙生物的品牌形象,更向外界…...
python自动化浏览器标签页的切换
#获取全部标签页的句柄返回句柄的列表 handleswebdriver.window_handles#获取全部标签页的句柄返回句柄的列表 print(len(handles)) 切换标签页 handleswebdriver.window_handles webdriver.switch_to.window(handles[index])#切换到第几个标签页就写几 关闭标签页 关闭标…...
大象机器人推出myCobot 280 RDK X5,携手地瓜机器人共建智能教育机
摘要 大象机器人全新推出轻量级高性能教育机械臂 myCobot 280 RDK X5,该产品集成地瓜机器人 RDK X5 开发者套件,深度整合双方在硬件研发与智能计算领域的技术优势,实现芯片架构、软件算法、硬件结构的全栈自主研发。作为国内教育机器人生态合…...
Redis 数据类型全解析:从基础到实战应用
精心整理了最新的面试资料和简历模板,有需要的可以自行获取 点击前往百度网盘获取 点击前往夸克网盘获取 Redis 作为高性能的键值对存储系统,其丰富的数据类型是实现复杂业务逻辑的核心优势。本文将深入解析 Redis 六大核心数据类型及扩展类型ÿ…...
第一天 unity3D 引擎入门
一、为什么选择Unity进行3D开发? Unity作为全球使用最广泛的游戏引擎,在2022年的开发者调查中占据了62%的市场份额。它不仅支持3D/2D游戏开发,更在VR/AR、工业仿真、影视动画等领域大放异彩。对于初学者而言,Unity的独特优势在于…...
【初阶数据结构】——算法复杂度
一、前言 1、数据结构是什么? 数据结构(Data Structure)是计算机存储、组织数据的⽅式,指相互之间存在⼀种或多种特定关系的数 据元素的集合。没有⼀种单⼀的数据结构对所有⽤途都有⽤,所以我们要学各式各样的数据结构, 如&…...
MySQL:存储函数和存储过程
系列文章目录 1.MySQL编程基础 2.程序控制流语句 3.存储过程 4.游标 5.嵌入式SQL 文章目录 系列文章目录前言一、程序控制流语句:二、存储函数: 1.存储函数的特点:2.存储函数的定义:3.调用存储函数 三、存储过程:…...
常见的 API 设计风格
在软件开发中,常见的 API 设计风格主要有以下几种,每种风格适用于不同的场景和需求: 1. RESTful API (主流) 特点: 基于 HTTP 协议,使用标准方法(GET/POST/PUT/DELETE)资源导向(UR…...
Google-A2A协议全面解析:一文掌握Agent-to-Agent协议的核心与应用
前言: 在当今人工智能技术飞速发展的时代,智能体(Agent)已悄然融入我们生活的各个角落。无论是个人智能助手,还是企业的自动化工具,各类AI代理的应用愈发广泛。但目前这些智能体之间大多处于孤立状态&…...
Linux-服务器添加审计日志功能
#查看audit软件是否在运行(状态为active而且为绿色表示已经在运行) systemctl start auditd #如果没有在运行的话,查看是否被系统禁用 (audit为0表示被禁用) cat /proc/cmdline | grep -w "audit=0" #修改/etc/default/grub里面audit=0 改为audit=1 #更新GRUB…...
基于机器视觉的多孔零件边缘缺陷检测(源码C++、opencv、凸包、凸缺陷检测)
👑主页:吾名招财 👓简介:工科学硕,研究方向机器视觉,爱好较广泛… 💫签名:面朝大海,春暖花开! 基于机器视觉的多孔零件边缘缺陷检测(源码C、ope…...
汇川PLC通信
汇川PLC通信协议及读写 引言 汇川PLC(Programmable Logic Controller,可编程逻辑控制器)广泛应用于工业自动化领域。汇川PLC支持多种通信协议,包括Modbus、Ethernet/IP、PPI等。本文将详细介绍汇川PLC的通信协议,并通…...
如何使用AI辅助开发CSS3 - 通义灵码功能全解析
一、引言 CSS3 作为最新的 CSS 标准,引入了众多新特性,如弹性布局、网格布局等,极大地丰富了网页样式的设计能力。然而,CSS3 的样式规则繁多,记忆所有规则对于开发者来说几乎是不可能的任务。在实际开发中,…...
MySQL入门:数据表的创建
今天我们来介绍一下除HTML外的另一种语言:MySQL语言; MySQL:即一种用于管理和处理关系数据库的标准语言。要用于执行查询、更新、管理数据库中的数据以及定义和操作数据库结构。 接下来我会逐一介绍它的作用以及其中数据表,数据…...
数据库的基本原则
数据库的核心原则 原子性与持久性:原子性(Atomicity)确保一个事务中的所有操作要么全部完成,要么完全不执行,不会出现部分完成的情况。持久性(Durability)则保证一旦事务提交成功,即…...
Rust 中的Relaxed 内存指令重排演示:X=0 Y=0 是怎么出现的?
🔥 Rust 中的内存重排演示:X0 && Y0 是怎么出现的? 在并发编程中,我们经常会听说“内存重排(Memory Reordering)”这个术语,但它似乎总是只出现在理论或者别人口中的幻觉里。本文将通过…...
C++进程间通信开发实战:高效解决项目中的IPC问题
C进程间通信开发实战:高效解决项目中的IPC问题 在复杂的软件项目中,进程间通信(Inter-Process Communication, IPC)是实现模块化、提高系统性能与可靠性的关键技术之一。C作为一门高性能的编程语言,广泛应用于需要高效…...
FPGA-DDS技术的波形发生器
1.实验目的 1.1掌握直接数字频率合成(DDS)的基本原理及其实现方法。 1.2在DE2-115 FPGA开发板上设计一个可调频率的正弦波和方波发生器,频率范围10Hz~5MHz,最小分辨率小于1kHz。 1.3使用Quartus II进行仿真,并通过S…...
C#实现通过MQTT Broker——EMQX发布订阅消息及其认证、授权的安全配置操作
一、准备内容 MQTT的构成、使用场景、工作原理介绍-CSDN博客文章浏览阅读656次,点赞7次,收藏12次。MQTT(Message Queuing Telemetry Transport)是一种轻量级、基于发布-订阅模式的消息传输协议【适用于资源受限的设备和低带宽、高延迟或不稳定的网络环境】它在物联网应用中…...
考研单词笔记 2025.04.15
addition n添加,增加,加法 additional a附加的,额外的 in addition 另外;除此之外;加之 augment v增加,增强,提高 explode v急剧增长,爆炸,爆发,迸发 gr…...
【双指针】三数之和(medium)
三数之和(medium) 题⽬描述:解法(排序双指针):算法思路:C 算法代码:Java 算法代码:注:数组转列表 题⽬链接:15. 三数之和 题⽬描述: …...
【项目管理】第17章 项目干系人管理-- 知识点整理
项目管理-相关文档,希望互相学习,共同进步 风123456789~-CSDN博客 (一)知识总览 项目管理知识域 知识点: (项目管理概论、立项管理、十大知识域、配置与变更管理、绩效域) 对应:第6章-第19章 第6章 项目管理概论 4分第13章 项目资源管理 3-4分第7章 项目…...
视频融合平台EasyCVR可视化AI+视频管理系统,打造轧钢厂智慧安全管理体系
一、背景分析 在轧钢厂,打包机负责线材打包,操作人员需频繁进入内部添加护垫、整理包装、检修调试等。例如,每班产线超过300件,12小时内人员进出打包机区域超过300次。若员工安全意识薄弱、违规操作,未落实安全措施就…...
无参数RCE
无参数RCE(Remote Code Execution,远程代码执行) 是一种通过利用目标系统中的漏洞,在不直接传递用户可控参数的情况下,实现远程执行任意代码的攻击技术。与传统的RCE攻击不同,无参数RCE不依赖外部输入参数…...
鸿蒙开发中,@Extend、@Styles 和 @Builder 的区别
在鸿蒙(HarmonyOS)开发中,Extend、Styles 和 Builder 是三种常用的装饰器,用于提升代码复用性和可维护性。以下是它们的详细介绍和示例: 1. Extend:扩展组件样式 说明: 功能:用于…...
C++ 智能指针底层逻辑揭秘:优化内存管理的核心技术解读
目录 0.为什么需要智能指针? 1.智能指针的使用及原理 RAII: 智能指针的原理: 2.智能指针有哪些? std::auto_ptr std::unique_ptr std::shared_ptr std::weak_ptr 0.为什么需要智能指针? 想要回答这个问题&…...
Vue接口平台学习七——接口调试页面请求体
一、实现效果图及简单梳理 请求体部分的左边,展示参数,分text和file类型。 右边部分一个el-upload的上传文件按钮,一个table列表展示,一个显示框,用于预览选择的文件,点击可大图展示。 二、页面内容实现 …...
小程序css实现容器内 数据滚动 无缝衔接 点击暂停
<view class"gundongBox"><!-- 滚动展示信息的模块 --><image class"imgWid" :src"imgurlgundong.png" mode"widthFix"></image><view class"gundongView"><view class"container&qu…...
内存条装机,无法启动
1、i5-9600k,主板技嘉z390gamingx: ①、插满4条DDR4-2666,无法启动; ②、两条DDR4-2666,插在2、4或者1、3插槽,可以启动; ③、三条DDR4-2666,一条DDR4-2400,插满4个内存插槽&…...
