算法通过村第十四关-堆|青铜笔记|堆结构

news2024/11/25 16:39:00

文章目录

  • 前言
  • 堆的概念和特征
  • 堆的构成过程
  • 插入操作
  • 删除操作
  • 总结


前言


若执于空,空亦为障。 --彼得·马西森《雪豹》

堆结构是一种非常重要的基础数据结构,也是算法的重要内容,很多题目甚至只能通过用堆来进行,所以我们必须明确什么类型的题目可以使用堆,以及如何使用堆来解决。由于堆的结构和维护的过程很复杂,因此一般面试不需要手写堆的实现,但是在Java、python、C++已经提供了一些工具,因此需要知道思路就可以了。

这里主要简介堆的使用,如何进行增删改查,不用管代码怎么写,后面我们会继续介绍怎么使用堆解决问题的。

堆的概念和特征

堆是将一组数据按照完全二叉树的存储顺序(推荐⭐⭐⭐: 算法通过村第六关-树青铜笔记|中序后序_师晓峰的博客-CSDN博客),将数据存储在一个一维数组中的结构。堆有两种结构,一种称为大顶堆,一种称为小顶堆,如图下:

  • 小顶堆:任意节点的值均小于它的左右孩子,并且最小值位于堆顶,即根节点处。
  • 大顶堆:任意节点的值均大于它的左右孩子,并且最大值位于堆顶,即根节点处。

当然有些地方叫大根堆,小根堆,或者最大堆、最小堆都是一个意思。大小的特征都是类似的,只是比较的时候按照大的来点定还是按照小的来定。我们这里介绍先按照最大堆来进行,后面的题目我们根据条件来定。

小顶堆:
在这里插入图片描述
大顶堆:
在这里插入图片描述
既然是将一组数据按照树的结构存储在一堆数组中,而且还是完全二叉树,那么父子之间的关系的建立就很重要了。

有个概念需要注意一下,我们在做题的时候经常会看到有地方叫做堆,有些地方叫优先队列,两者是什么关系呢?

优先队列:说到底还是一种队列,他的工作就是poll()/peek()出队列中的最大或者最小的那个元素,所以叫做带有优先级别的队列。能够实现这样的功能的策略不一定是堆。例如:二项堆、平衡树、线段树、C++里面还用二进制分组vector来实现一个优先队列。

堆:是一个很大的概念,它并不一点是完全二叉树。我们之前用完全二叉树是因为这个容易呗数组存储,但是除了这种二叉堆之外,还有二项堆、斐波那契堆。这种堆就不属于二叉树了。

所以说,优先队列和堆不是一个同level的概念,但是Java中PriorityQueue就是采用堆实现的,因此在Java的领域中,我们可以认为堆就是优先队列,优先队列也就是堆,换个场景的话就不太行了。

堆的构成过程

使用数组构建堆时,就是按照层次将所有元素依次放入二叉树中,使其成为二叉树,然后再不断的调整,最终使其符合堆的结构。

这里我们先假设一个节点下标为 i:

  1. 当 i == 0 时, 为根节点。
  2. 当 i >= 1 时, 父节点为 (i - 1) / 2;

size 就是元素的个数,从 1 开始计数。

下面就看一下怎么建立一个大顶堆:

将元素依次排到完全二叉树节点上,如左图所示:
在这里插入图片描述

  • int i = (size - 2) / 2 = 4 (思考这里为什么使用 size - 2 而不是size - 1)。 找到数组下标 4
    号,65 大于取其孩子,满足大顶堆的性质,不用交换。如下图:

在这里插入图片描述

  • 然后 i = i- 1;然后用 2 和其他孩子比较, 2 和 204 交换。交换之后 204 所在的子树满足大顶堆,如下图所示:

在这里插入图片描述

  • 54 和其他孩子比较,54 和 92 交换,此时92 所在子树满足大顶堆,如下图:

在这里插入图片描述

  • 继续,23 和其他孩子比较,23 和 204 交换,交换完之后,23 的子树却不满足了需要再调整如下图:
    在这里插入图片描述

  • 12 和 204 交换,然出现不平衡的情况,依次类推,知道根节点也满足要求就完毕了。
    在这里插入图片描述
    这样我们就建好了一个大顶堆,从图中可以看到,根元素是整个树中值最大的那个,二第二大和第三大就是其左右子树,具体那个更大是未知数,需要比较一下才知道。

另外,对于同一组数据,如果输入的序列不一样,最终的构造的树是否也会不一样呢?非常有可能,那么这样的树有什么意义呢?我们再往后面看看你,这里你已经理解怎么构建了对吧。

插入操作

从上面可以看到根节点和其左右节点是堆的老大老二老三,其他节点则是没有太明显的规律,那么如果要插入一个新的元素呢,该怎么办?直接说规则了:

将元素插入到保持其完全二叉树的最后一个位置,然后顺着这支一直向上调整,每前进一层就要保证其他子树都满足堆的要求,否则去调整子树,直到全部满足要求。

看一个例子,如下图,要插入 300 ,我们将其插入到 31的右孩子位置,然后不断向上爬, 31 < 300 ,所以两者需要交换,再向上 300 比 65 大,所以两者也要交换。最后 300 比根元素 204 大,两者也要交换,最后得到了新的堆。完整的过程如下:

在这里插入图片描述

删除操作

堆本身比较特殊,一般对堆中的数据进行操作都是针对堆顶的元素,即每次都从堆中获取得到最大或者最小值,其他得不关心,所以我们删除得时候,也删除堆顶元素。如果直接删掉堆顶,整个结果被破坏,群龙无首。所以实际策略是先将堆中最后一个元素,(假如为A)和堆顶元素进行替换,然后再删除堆中最后一个元素,之后再从跟开始逐步与之左右比较,谁得更大谁上位。然后A再继续与子树比较,如果有更大得继续交换,直到自己所在得子树也满足大顶堆得要求。

(上面得过程可以理解为:皇帝突然驾崩了,然后先找个顾命大臣维持局面,大臣先看看那个皇子更强大,谁就是老大。然后大臣就逐步隐退,找到属于自己得位置)
在这里插入图片描述
最后调整一下位置,满足堆得性质:

在这里插入图片描述
说了这么多,你觉得他得价值再哪里呢?价值在于大顶堆得根节点是整个树最大得那个,增加时会根据根得大小来决定要不要加,而删除操作只删除根元素。这个特征可以再很多场景下有巧妙得应用,后面得算法题目大多都是基于此得。

这里可能有很多人有疑问,感觉不管时插入还是删除,堆得操作都不简单,那么为什么还说堆得效率比较高呢?

这是因为堆元素得数量时有限制得,一般不用将所有得元素都放入堆里。后面题目中可以看到这些,在序列中找K大,则堆得大小就是k。如果K个链表合并,那么堆就是K。原理后面再展开详细展开。

说了这么多堆得性质了,我们来看看堆是怎么解决问题得。关于堆得问题,记住这里(我有秘法传于世间💕:

查找:找大用小,大的进;找小用大,小的进。
排序:升序用小,降序用大。

查找的方法就是:找 k 大, 则用小顶堆,后序的数据只有比根元素更大时才允许进入堆。如果找 k 小,则反过来。这我们后面接着分析。留个疑惑。


总结

提示:堆结构;堆的特性;堆的构造;堆的插入操作;堆的删除操作:


如果有帮助到你,请给题解点个赞和收藏,让更多的人看到 ~ ("▔□▔)/

如有不理解的地方,欢迎你在评论区给我留言,我都会逐一回复 ~

也欢迎你 关注我 ,喜欢交朋友,喜欢一起探讨问题。
在这里插入图片描述

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

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

相关文章

AnyLogic Pro 8.8.4 Crack

为什么选择 AnyLogic 仿真软件&#xff1f; 行业特定库 用于通用业务流程或工作流程的流程建模库。 流体库可模拟采矿或石油天然气等行业的散装货物和液体输送。 用于铁路运输、码头和堆场的铁路图书馆。 行人图书馆&#xff0c;用于记录机场、体育场馆、车站或购物中心的行人…

深度学习环境 | Linux下安装,卸载,查看pytorch版本

一 在Linux下安装pytorch 1 进入Linux环境以后 新建一个名为pytorch的虚拟环境&#xff0c;执行以下代码&#xff1a; conda create -n pytorch python3.82 激活新建的pytorch虚拟环境&#xff0c;执行以下代码&#xff1a; conda activate pytorch # conda版本较新使用这条…

目录启示:PHP 与命名空间的声明

文章目录 参考环境命名空间概念版本支持影响范围 全局命名空间概念魔术常量 \_\_NAMESPACE\_\_声明全局命名空间 声明命名空间为空间命名命名规则核心命名空间 子命名空间的声明在同一文件中定义多个命名空间无括号命名空间声明有括号命名空间声明禁止混合使用推荐使用有括号命…

【Python学习笔记】类型/运算/变量/注释

前言 人生苦短&#xff0c;追求生产力&#xff0c;做一只时代风口的猪&#xff0c;应该学python Python语言中&#xff0c;所有的数据都被称之为对象。 1. 对象类型 Python语言中&#xff0c;常用的数据类型有&#xff1a; 整数&#xff0c; 比如 3 小数&#xff08;也叫浮…

如何查找文献,如何阅读文献

一、高效查找需要阅读的文献 1、首先进入知网的高级检索页&#xff0c;点击“学术期刊”&#xff0c;你会看到“来源类别”选择&#xff0c;在这个里选择北核和C刊 2、在检索结果页选择一篇自己感兴趣的文章&#xff0c;点击篇名进入文章详情页&#xff0c;下拉可看到核心文献…

高速数字化仪和AWG在车辆总线(CAN/LIN/PSI5)测试中的应用(二)

前情回顾 上期德思特向大家介绍了德思特模块化数字化仪在车辆测试中的应用&#xff0c;8到16位的通道&#xff0c;高达5 GS/s的采样率允许选择与应用相匹配的快速或慢速采样&#xff0c;即使缺少组件&#xff0c;它们也可以进行测试。这期将为大家介绍如何使用信号源进行仿真&…

呼吁社区共同维护Sui品牌和商标

Sui社区成员可以通过举报Sui商标和品牌资产的不当使用来帮助保护网络的信誉。Sui商标政策解释了logo和名称的可接受和不可接受的使用方式。这些展示代表Sui面向公众&#xff0c;而善意行为者的正确使用有助于维护Sui的声誉。 Sui网络在公众中享有良好声誉&#xff0c;Sui社区都…

遥感影像的面向对象方法

面向对象分割算法是一种将图像中的像素分割成不同的对象的算法。它通过对像素进行聚类&#xff0c;将相似的像素分为同一个对象&#xff0c;从而实现图像分割的目的。常见的面向对象分割算法包括基于区域的分割算法、基于边缘的分割算法和基于能量的分割算法等。 其中&#xff…

【2023年11月第四版教材】专题1 - 计算题考点汇总 (合集篇)

专题1 - 计算题考点汇总 (合集篇&#xff09; 1 进度类1.1 PERT三点估算1.1.1 β分布1.1.2 三角分布 1.2 单代号网络图1.2.1 画图1.2.2 找关键路径1.2.3 计算总工期1.2.4 总时差1.2.5 自由时差1.2.6 工期压缩 1.3 双代号网络图1.4 双代号时标网络图1.4.1 画图1.4.2 找关键路径1…

大公司产品经理都用哪些原型工具?

原型设计工具的应用场景包括产品展示、产品需求规划和抽象到具体呈现&#xff0c;那么如何根据应用场景选择合适的原型工具呢&#xff1f;不用说&#xff0c;本文列出了常用的原型设计工具&#xff0c;看看你最想选择哪一个&#xff01; 即时设计 即时设计是国内一款专业级的…

java非文本文件copy

文本文件使用字符流来处理 非文本文件使用字节流来处理 字节流处理代码整理 public void copyFile(String srcPath, String desPath) {FileInputStream fileInputStream null;FileOutputStream fileOutputStream null;try {File srcFile new File(srcPath);File desFile ne…

链表(3):双链表

引入 我们之前学的单向链表有什么缺点呢&#xff1f; 缺点&#xff1a;后一个节点无法看到前一个节点的内容 那我们就多设置一个格子prev用来存放前面一个节点的地址&#xff0c;第一个节点的prev存最后一个节点的地址&#xff08;一般是null&#xff09; 这样一个无头双向…

Dart-C、Dart-Kotlin/Java/Swift/Object-C、Kotlin-C数据类型对照表

参考一&#xff1a;Dart FFI 数据类型映射 一、Dart—C 的数据类型对照 二、Dart—Java/Kotlin/Object-C/Swift 的数据类型对照 三、C—Kotlin 的数据类型对照

WordPress发布文章上传图片如何默认选择全尺寸

最近发现每次上传图片插入到文章中&#xff0c;图片默认选择缩略图大小并靠左&#xff0c;每次都需要手动修改一下图片信息&#xff0c;比较麻烦。 今天为大家提供修改默认上传图片大小和对齐方式等。 将代码添加到functions.php&#xff1a; //WordPress 设置图片的默认显示…

Qt 样式表大全整理

【QT】史上最全最详细的QSS样式表用法及用例说明_qt样式表使用大全_半醒半醉日复日&#xff0c;花落花开年复年的博客-CSDN博客 QT样式表的使用_qt 设置按下 release hover 按钮样式表_create_right的博客-CSDN博客 QPushButton {border-image: url(:/Start_Stop.png); } QPu…

H5营销观察:场景应用的重要性

H5营销是很常见的营销方式&#xff0c;通常用于各种营销活动和推广活动。对于品牌部或市场部人员&#xff0c;提到“场景化营销”&#xff0c;很多人的第一反应就是如何制作一个有创意、能快速传播的H5。 似乎H5营销已经成为市场人专业度的考量&#xff0c;不论是品牌宣传、活动…

001flutter基础学习

flutter基础学习 参考:https://book.flutterchina.club/chapter1/flutter_intro.html Flutter是谷歌的移动UI框架跨平台: Linux,Android, IOS,Fuchsia原生用户界面:它是原生的,让我们体验更好,性能更好开源免费&#xff1a;完全开源,可以进行商用Flutter与主流框架的对比 Cor…

Rt-Thread 移植4--对象容器实现(KF32)

1.对象 1,1 什么是对象 所有的数据结构都是对象 1.2代码实现 1.2.1 对象类型枚举定义 rtdef.h 添加rt_object_class_type enum rt_object_class_type{RT_Object_Class_NULL0,RT_Object_Class_Thread ,RT_Object_Class_Semaphore,RT_Object_Class_Mutex,RT_Object_Class_E…

【java学习】JavaBean(28)

文章目录 1. 概念 1. 概念 JavaBean 是一种 Java 语言写成的可重用组件。 所谓 javaBean &#xff0c;是指符合如下标准的 Java 类&#xff1a; (1) 类是公共的 (2) 有一个无参的公共的构造器 (3) 有属性&#xff0c;属性一般是私有的&#xff0c;且有对应的 get 、set 方法 …

cad问题:无法识别的版本,不能读取

cad安装目录或文件名、新建时的文件模板&#xff0c;含有“无”这个字就会出现此问题&#xff0c;只要把 无这个字改成没&#xff0c;即可解决