二叉堆解读

在数据结构和算法中,二叉堆是一种非常重要的数据结构,它被广泛用于实现优先队列、堆排序等场景。本文将介绍二叉堆的基本概念、性质、操作以及应用场景。

一、基本概念

二叉堆是一种特殊的完全二叉树,它满足堆性质:对于每个节点i,其子节点的值(或关键字)要么都小于等于节点i的值(称为最小堆),要么都大于等于节点i的值(称为最大堆)。二叉堆通常通过数组来实现,以便于存储和访问。

最大堆: 任何一个父节点都大于或等于它的左右子节点, 最大堆的最大元素再堆顶
在这里插入图片描述

最小堆: 任何一个父节点都小于或等于它的左右子节点,最小堆的最小元素再堆顶

在这里插入图片描述

二、性质

  1. 结构性质:二叉堆是一棵完全二叉树,除了最后一层外,其他层的节点都是满的,且最后一层的节点都靠左对齐。
  2. 堆性质:对于每个节点i,其子节点的值满足最小堆或最大堆的要求。

三、基本操作

插入(Insert):向二叉堆中插入一个新元素。首先,将新元素添加到数组的末尾,然后通过上浮操作(percolate up)调整堆结构,以满足堆性质。

当二叉堆插入节点时,插入位置是完全二叉树的最后一个位置。例如插入一个新节点,值是 0。

在这里插入图片描述

这时,新节点的父节点5比0大,显然不符合最小堆的性质。于是让新节点“上浮”,和父节点交换位置。

在这里插入图片描述

继续用节点0和父节点3做比较,因为0小于3,则让新节点继续“上浮”。

在这里插入图片描述

继续比较,最终新节点0“上浮”到了堆顶位置。

在这里插入图片描述

删除(Delete):从二叉堆中删除一个元素。通常,我们删除堆顶元素(即数组的第一个元素),然后用数组的最后一个元素替换堆顶元素,并通过下沉操作(percolate down)调整堆结构。

二叉堆删除节点的过程和插入节点的过程正好相反,所删除的是处于堆顶的节点。例如删除最小堆的堆顶节点1。

在这里插入图片描述

这时,为了继续维持完全二叉树的结构,我们把堆的最后一个节点10临时补到原本堆顶的位置。

在这里插入图片描述

接下来,让暂处堆顶位置的节点10和它的左、右孩子进行比较,如果左、右孩子节点中最小的一个(显然是节点2)比节点10小,那么让节点10“下沉”。

在这里插入图片描述

继续让节点10和它的左、右孩子做比较,左、右孩子中最小的是节点7,由于10大于7,让节点10继续“下沉”。

在这里插入图片描述

这样一来,二叉堆重新得到了调整。

四、代码实现

class BinaryHeap:def __init__(self, elements=None, max_heap=True):"""初始化二叉堆。:param elements: 可选参数,一个列表,用于构建初始堆。:param max_heap: 是否为最大堆,默认为True。"""self.heap = []self.max_heap = max_heapif elements:for element in elements:self.insert(element)def parent(self, i):"""计算给定索引i的父节点索引。:param i: 子节点的索引。:return: 父节点的索引。"""return (i - 1) // 2def left_child(self, i):"""计算给定索引i的左孩子节点索引。:param i: 父节点的索引。:return: 左孩子节点的索引。"""return 2 * i + 1def right_child(self, i):"""计算给定索引i的右孩子节点索引。:param i: 父节点的索引。:return: 右孩子节点的索引。"""return 2 * i + 2def swap(self, i, j):"""交换堆中索引为i和j的元素。:param i: 第一个元素的索引。:param j: 第二个元素的索引。"""self.heap[i], self.heap[j] = self.heap[j], self.heap[i]def sift_up(self, i):"""上浮操作,确保以i为根的子树满足堆的性质。:param i: 子树根节点的索引。"""while i > 0:parent_i = self.parent(i)if (self.max_heap and self.heap[parent_i] < self.heap[i]) or \(not self.max_heap and self.heap[parent_i] > self.heap[i]):self.swap(parent_i, i)i = parent_ielse:breakdef sift_down(self, i, heap_len):"""下沉操作,确保以i为根的子树满足堆的性质。:param i: 子树根节点的索引。:param heap_len: 堆的当前长度(元素数量)。"""largest = ileft = self.left_child(i)right = self.right_child(i)if left < heap_len and ((self.max_heap and self.heap[left] > self.heap[largest]) or(not self.max_heap and self.heap[left] < self.heap[largest])):largest = leftif right < heap_len and ((self.max_heap and self.heap[right] > self.heap[largest]) or(not self.max_heap and self.heap[right] < self.heap[largest])):largest = rightif largest != i:self.swap(i, largest)self.sift_down(largest, heap_len)def insert(self, key):"""向堆中插入一个元素。:param key: 要插入的元素。"""self.heap.append(key)self.sift_up(len(self.heap) - 1)def delete_max(self):"""删除并返回堆中的最大元素(对于最大堆)。:return: 删除的元素。"""if not self.heap:return Noneif len(self.heap) == 1:return self.heap.pop()max_val = self.heap[0]self.heap[0] = self.heap.pop()self.sift_down(0, len(self.heap))return max_valif __name__ == '__main__':b_heap = BinaryHeap([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], max_heap=False)b_heap.insert(0)print(b_heap.delete_max())print(b_heap.delete_max())

五、应用场景

  1. 优先队列:二叉堆是实现优先队列的理想数据结构。在优先队列中,元素的优先级由它们的值决定。通过插入和删除操作,我们可以高效地添加和移除具有最高(或最低)优先级的元素。
  2. 堆排序:堆排序是一种基于二叉堆的排序算法。它首先构建一个最大堆,然后将堆顶元素与末尾元素交换,并将剩余元素重新调整为最大堆。重复这个过程,直到所有元素都排好序。堆排序的时间复杂度为O(nlogn),且空间复杂度为O(1)。

六、总结

二叉堆是一种高效的数据结构,它利用堆性质实现了快速插入、删除和查找操作。在优先队列、堆排序等场景中,二叉堆发挥着重要作用。掌握二叉堆的实现和应用,对于提高算法效率和理解数据结构具有重要意义。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/796263.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

电子商务平台中大数据的应用|主流电商平台大数据采集API接口

(一)电商平台物流管理中大数据的应用 电商平台订单详情订单列表物流信息API接口应用 电子商务企业对射频识别设备、条形码扫描设备、全球定位系统及销售网站、交通、库存等管理软件数据进行实时或近实时的分析研究,提高物流速度和准确性。部分电商平台已建立高效的物流配送网…

【STL】vector的底层原理及其实现

vector的介绍 vector是一个可变的数组序列容器。 1.vector的底层实际上就是一个数组。因此vector也可以采用连续存储空间来存储元素。也可以直接用下标访问vector的元素。我们完全可以把它就当成一个自定义类型的数组使用。 2.除了可以直接用下标访问元素&#xff0c;vector还…

掌握数据相关性新利器:基于R、Python的Copula变量相关性分析及AI大模型应用探索

在工程、水文和金融等各学科的研究中&#xff0c;总是会遇到很多变量&#xff0c;研究这些相互纠缠的变量间的相关关系是各学科的研究的重点。虽然皮尔逊相关、秩相关等相关系数提供了变量间相关关系的粗略结果&#xff0c;但这些系数都存在着无法克服的困难。例如&#xff0c;…

解决win7作为虚拟机无法复制粘贴共享文件的问题

win7作为虚拟机经常会出现无法与主机的剪切板共享、文件共享。 归根结底是win7虚拟机里面没有安装VMware Tools 能够成功安装vmware tools的条件&#xff1a; 1&#xff09;win7版本为win7 sp1及以上 2&#xff09;安装KB4490628&#xff0c;KB4474419补丁 因此下面来详细介绍…

【LeetCode题解】2192. 有向无环图中一个节点的所有祖先+1026. 节点与其祖先之间的最大差值

文章目录 [2192. 有向无环图中一个节点的所有祖先](https://leetcode.cn/problems/all-ancestors-of-a-node-in-a-directed-acyclic-graph/)思路&#xff1a;BFS记忆化搜索代码&#xff1a; 思路&#xff1a;逆向DFS代码&#xff1a; [1026. 节点与其祖先之间的最大差值](https…

为什么说AI的尽头是生物制药?

AI的尽头究竟是什么&#xff1f;有投资者说是光伏&#xff0c;也有投资者说是电力&#xff0c;而英伟达给出的答案则是生物制药。 在英伟达2023年投资版图中&#xff0c;除AI产业根基算法与基础建设外&#xff0c;生物制药是其重点布局的核心赛道。英伟达医疗保健副总裁Kimber…

FastEI论文阅读

前言 研究FastEI&#xff08;Ultra-fast and accurate electron ionization mass spectrum matching for compound identification with million-scale in-silico library&#xff09;有很长时间了&#xff0c;现在来总结一下&#xff0c;梳理一下认知。PS&#xff1a;为什么要…

【LeetCode: 21. 合并两个有序链表 + 链表】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

axios快速入门

一、环境配置 1.1概述 上古浏览器页面在向服务器请求数据时&#xff0c;因为返回的是整个页面的数据&#xff0c;页面都会强制刷新一下&#xff0c;这对于用户来讲并不是很友好。并且我们只是需要修改页面的部分数据&#xff0c;但是从服务器端发送的却是整个页面的数据&#…

攻防世界 Broadcast 题目解析

Broadcast 一&#xff1a;题目 二&#xff1a;解析 将压缩包解压&#xff0c;得到如上图所示&#xff0c;打开task.py&#xff0c;之后得到flag 这个有点简单了&#xff0c;不要被解压后文件太多所迷惑。

InnoDB中的索引方案

文章目录 InnoDB中的索引方案 InnoDB支持多种类型的索引&#xff0c;包括B-tree索引、全文索引、哈希索引等。B-tree索引是InnoDB存储引擎的默认索引类型&#xff0c;适用于所有的数据类型&#xff0c;包括字符串、数字和日期等。 以下是创建InnoDB表及其B-tree索引的示例代码…

VBA数据库解决方案第九讲:把数据库的内容在工作表中显示

《VBA数据库解决方案》教程&#xff08;版权10090845&#xff09;是我推出的第二套教程&#xff0c;目前已经是第二版修订了。这套教程定位于中级&#xff0c;是学完字典后的另一个专题讲解。数据库是数据处理的利器&#xff0c;教程中详细介绍了利用ADO连接ACCDB和EXCEL的方法…

2024年阿里云4核8G服务器多少钱一年?4C8G服务器955元

阿里云服务器4核8G租用优惠价格955元一年&#xff0c;配置为云服务器ECS通用算力型u1实例4核8G配置、ESSD Entry盘20G-40G、1M-3M带宽&#xff0c;实例规格为ecs.u1-c1m2.xlarge&#xff0c;阿里云优惠活动 yunfuwuqiba.com/go/aliyun 活动链接打开如下图&#xff1a; 阿里云4核…

【数据结构】ArrayList详解

目录 前言 1. 线性表 2. 顺序表 3. ArrayList的介绍和使用 3.1 语法格式 3.2 添加元素 3.3 删除元素 3.4 截取部分arrayList 3.5 其他方法 4. ArrayList的遍历 5.ArrayList的扩容机制 6. ArrayList的优缺点 结语 前言 在集合框架中&#xff0c;ArrayList就是一个…

spring boot学习第十六篇:配置多数据源

1、代码参考&#xff1a; dynamic-ds/spring-boot-dynamic-ds at main veminhe/dynamic-ds GitHub 2、验证 2.1调用POST接口http://localhost:8081/hmblogs/blog/addBlog 2.2改动数据源为BJ 然后调用接口添加数据 然后查看ds0库的博客数据

【最新可用】Claude国内镜像,可上传图片,可用Claude3全系模型(包括Pro版本的Opus)!亲测比GPT好用!

亲测可用&#xff0c;镜像地址&#xff1a;Claude 3 镜像 使用方法 访问镜像&#xff1a;Claude 3 镜像 2. 点击设置&#xff0c;配置授权码&#xff0c;关闭设置。这里免费赠送一个体验版的授权码 sk-SZcJyvx3RXRID624E2D3795578Df44C7Af03F2909a8f5eA0 即可发起对话啦&…

Android Studio学习9——使用Logcat打印日志

在Android开发中&#xff0c;Logcat是一个工具&#xff0c;它允许开发者查看设备或模拟器的日志信息。开发者可以使用Log类来打印日志信息&#xff0c;这对于调试和错误排查非常有帮助。 v 或 verbose: 最低等级&#xff0c;显示所有消息。d 或 debug: 用于调试消息。i 或 info…

深入浅出 -- 系统架构之负载均衡Nginx动静分离

一、Nginx动静分离 动静分离应该是听的次数较多的性能优化方案&#xff0c;那先思考一个问题&#xff1a;为什么需要做动静分离呢&#xff1f;它带来的好处是什么&#xff1f; 其实这个问题也并不难回答&#xff0c;当你搞懂了网站的本质后&#xff0c;自然就理解了动静分离的重…

Docker安装mysql并且设置主从

Docker安装部署mysql 下载镜像 docker pull mysql:5.7.35查看镜像 docker images启动 直接启动不挂载文件 docker run -p 3306:3306 --name mysql -e MYSQL_ROOT_PASSWORD123456 -d mysql:5.7.35挂载文件 docker run -p 3306:3306 --name mysql \ -v /usr/local/docker/m…

【Linux】环境基础开发工具使用——gcc/g++使用

Linux编译器-gcc/g使用 1. 背景知识 1. 预处理&#xff08;进行宏替换 ) 2. 编译&#xff08;生成汇编 ) 3. 汇编&#xff08;生成机器可识别代码&#xff09; 4. 连接&#xff08;生成可执行文件或库文件 ) 2. gcc如何完成 格式 gcc [ 选项 ] 要编译的文件 [ 选…