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

数据结构秘籍(四) 堆 (详细包含用途、分类、存储、操作等)

1 引言 

什么是堆?

堆是一种满足以下条件的树:(树这一篇可以参考我的文章数据结构秘籍(三)树 (含二叉树的分类、存储和定义)-CSDN博客)

堆中的每一个结点值都大于等于(或小于等于)子树中所有结点的值。

很多博客说堆是完全二叉树,其实并非如此,堆不一定是完全二叉树,只是为了方便存储和索引,我们通常用完全二叉树的形式来表示堆,事实上,广为人知的斐波那契堆和二项堆就不是完全二叉树,它们甚至都不是二叉树。
• (二叉)堆是一个数组,它可以被看成是一个 近似的完全二叉树。——《算法导论》第三版

判断一下下面给出的图是否是堆

 第1 个和第 2 个是堆。第 1 个是最大堆,每个节点都比子树中所有节点大。第 2 个是最小堆,每个节点都比子树中所有节点小。第3个不是,在第三个中,有的结点比子结点小,有的比子结点大不符合堆的特性。

2 堆的用途

当我们只关心所有数据中的最大值或者最小值,存在多次获取最大值或者最小值,多次插入或删除数据时,就可以使用堆。

对比有序数组而言,初始化一个有序数组时间复杂度是 O(nlog(n)),查找最大值或者最小值时间复杂度都是 O(1),但是,涉及到更新(插入或删除)数据时,时间复杂度为 O(n),即使是使用复杂度为 O(log(n)) 的二分法找到要插入或者删除的数据,在移动数据时也需要 O(n) 的时间复杂度。

相对于有序数组而言,堆的主要优势在于插入和删除数据效率较高。 因为堆是基于完全二叉树实现的,所以在插入和删除数据时,只需要在二叉树中上下移动节点,时间复杂度为O(log(n)),相比有序数组的 O(n),效率更高。

不过,需要注意的是:Heap 初始化的时间复杂度为 O(n),而非O(nlogn)

3 堆的分类

堆分为最大堆和最小堆。二者的区别在于结点的排序方式。

  • 最大堆:堆中的每一个结点的值都大于等于子树中所有结点的值。
  • 最小堆:堆中的每一个结点的值都小于等于子树中所有结点的值。

在下图中,图1是最大堆,图2是最小堆。

4 堆的存储

之前介绍树的时候说过,由于完全二叉树的优秀性质,利用数组存储二叉树即节省空间,又方便索引(若根结点的序号为 1,那么对于树中任意节点 i,其左子节点序号为 2*i,右子节点序号为 2*i+1)。

为了方便存储和索引,(二叉)堆可以用完全二叉树的形式进行存储。存储的方式如下图所示:

5 堆的操作

堆的更新操作主要包括两种:插入元素和删除堆顶元素。操作过程需要着重掌握和理解。

5.1 插入元素

在堆内进行插入的时候,我们会将插入的元素放到最后

5.1.1 将要插入的元素放到最后

5.1.2 从底向上,如果父结点比该元素小,则该结点和父结点交换 ,直到无法交换

 

5.2 删除堆顶元素(这里拿最大堆举例)

 根据堆的性质可以知道,最大堆的堆顶元素为所有元素中最大的,最小堆的堆顶元素是所有元素中最小的。当我们需要多次查找最大元素或者最小元素的时候,可以利用堆来实现。

删除堆顶元素后,为了保持堆的性质,需要对堆的结构进行调整,我们将这个过程称之为“堆化”,堆化的方法分为两种:

  • 一种是自底向上的堆化,上述的插入元素所使用的就是自顶向上的堆化,元素是从最底部向上移动。
  • 另一种是自顶向下堆化,元素由最顶部向下移动。
5.2.1 自底向上堆化

打个比方,如果一个公司里出现了boss离职的情况,该怎么办,看下文

首先删除堆顶元素,使得数组中下标为1的位置空出。

那谁来顶替这个位置,必须是数足够大。所以我们比较根结点的左子结点和右子结点,也就是下标为2,3的数组元素,将较大的元素填充到根结点的位置。

这时候,空出来的位置,就依次往下递归,谁有能力谁就上。也就是说,一直循环比较空出位置的左右子结点,并将大者移至空位,直到遍历到堆的最底部。

 

我们可以看到,这个时候已经完成了自底向上的堆化,没有元素可以填补空缺了,但是,我们可以看到数组中出现了空白,这将会导致存储空间的浪费。

5.2.2 自顶向下堆化 

自顶向下堆化,有一个特殊的点就是我们需要将堆的最后一个元素从末尾的位置提到堆顶(根结点)上来,再进行堆化。

 

我们不断的将这个(原来的) 末尾元素,不断地与左右子结点的值进行比较,和较大的子结点交换位置,直到无法交换为止

可能有的小伙伴要问了,这两个也没有什么太大的区别啊,重点就在自顶向下堆化不会产生气泡。

5.3 总结堆的操作

  • 插入元素:先将元素放置到元素末尾,再自底向上堆化,使末尾元素上浮。
  • 删除堆顶元素:将末尾元素放置堆顶,再自顶向下堆化,将堆顶元素下沉。也可以自底向上堆化,只是会产生空缺,浪费存储空间。最好采用自顶向下的堆化方式。

6 堆排序

堆排序的过程分为两步:

  1. 第一步是建堆,将一个无序的数组建立为一个堆。
  2. 第二步是排序,将堆顶元素取出,然后对剩下的元素进行堆化,反复迭代,直到所有的元素被取出为止。

6.1 建堆

建堆的过程就是一个对所有非叶子结点的自顶向下堆化过程。

什么是非叶子结点,就是最后一个结点的父结点及它之前的元素,都是非叶子结点(具体可以了解另外一篇关于树的相关内容,这里不详谈)。数据结构秘籍(三)树 (含二叉树的分类、存储和定义)-CSDN博客文章浏览阅读689次,点赞27次,收藏22次。根结点的序号为1,对于每个结点Node,假设它存储在数组中下标为i的位置,那么它的左子结点就存储在2i的位置,它的右子结点就存储在下标为2i+1的位置。二叉树的第i层最多拥有2的(n-1)次方个结点,深度为k的二叉树至多有2^(k+1)-1个结点(满二叉树),至少有2的n次方个结点,这里面的k为深度。二叉树的先序遍历是先输出根结点,再遍历左子树,最后遍历右子树,遍历右子树和左子树的时候同样 遵循先序遍历的规则,也就是说,我们可以递归实现先序遍历。并且,二叉树的分支具有左右次序,不能随意颠倒。 https://blog.csdn.net/rc1596919047/article/details/145934474?spm=1001.2014.3001.5501也就是说,如果结点个数为n,那么我们需要对n/2到1的结点进行自顶向下堆化。

将初始的无序数组抽象为一棵树,图中的结点个数为6个,所以4,5,6结点为叶子结点,1,2,3结点为非叶子结点,所以要对1-3号结点进行自顶向下堆化,注意顺序是从后往前堆化,从3号结点开始,一直到1号结点。(为什么是结点3,n为6,非叶子结点就是3-1)。

例如这张图,非叶子结点就是从5开始到1。(画的比较抽象,不喜勿喷)

回去看,3号结点堆化结果:

 2号结点堆化结果:

1号结点堆化结果:

 

至此,数组所对应的树已经成为了一个最大堆,建堆完成。

额外注意的是,堆化是一个完整的过程,而非一个步骤。

6.2 排序

由于堆顶元素是所有元素中最大的,所以我们重复取出堆顶元素,将这个最大的堆顶元素放置数组末尾,并对剩下的元素进行堆化即可。

现在思考两个问题:

  1. 删除堆顶元素后需要执行自顶向下堆化,还是自底向上堆化?
  2. 取出的堆顶元素存在哪,新建一个数组存吗?

先回答第一个问题,我们需要执行自顶向下堆化,这个堆化一开始要将末尾元素移动至堆顶,这个时候末尾的位置就空出来了,由于堆中的元素已经减小,这个位置不会再被使用,所以我们可以将取出的元素放在末尾。这其实就是做了一次交换操作,将堆顶和末尾的元素调换位置,从而将取出堆顶元素和堆化的第一步(将末尾元素放置根结点)进行合并。

取出第一个元素并堆化:

取出第二个元素并堆化:

取出第三个元素并堆化:

 

取出第四个元素并堆化:

 

取出第五个元素并堆化:

 

取出第六个元素并堆化:

堆排序就此完成。 

如果觉得我的讲解有不足之处,可以在评论区发表意见,我会及时采纳改正。更细致的,可以去看一看这篇文章:

数据结构堆(Heap)详解-堆的建立、插入、删除、最大堆、最小堆、堆排序等_最大堆 heap 是一个什么样的存在?-CSDN博客文章浏览阅读7.9w次,点赞153次,收藏447次。基本概念:1、完全二叉树:若二叉树的深度为h,则除第h层外,其他层的结点全部达到最大值,且第h层的所有结点都集中在左子树。2、满二叉树:满二叉树是一种特殊的的完全二叉树,所有层的结点都是最大值。什么是堆?堆(英语:heap)是计算机科学中一类特殊的数据结构的统称。堆通常是一个可以被看做一棵树的数组对象。堆总是满足下列性质:堆中某个节点的值总是不大于或不小于其父节点的值;..._最大堆 heap 是一个什么样的存在? https://blog.csdn.net/xiaomucgwlmx/article/details/103522410

相关文章:

数据结构秘籍(四) 堆 (详细包含用途、分类、存储、操作等)

1 引言 什么是堆? 堆是一种满足以下条件的树:(树这一篇可以参考我的文章数据结构秘籍(三)树 (含二叉树的分类、存储和定义)-CSDN博客) 堆中的每一个结点值都大于等于&#xff08…...

前端正则表达式完全指南:从入门到实战

文章目录 第一章:正则表达式基础概念1.1 什么是正则表达式1.2 正则表达式工作原理1.3 基础示例演示 第二章:正则表达式核心语法2.1 元字符大全表2.2 量词系统详解2.3 字符集合与排除 第三章:前端常用正则模式3.1 表单验证类3.1.1 邮箱验证3.1…...

【SRC实战】小游戏漏洞强制挑战

小游戏业务分析: 1、挑战成功加分,失败减分,存在段位机制,段位影响榜单排名 2、随机推荐挑战对象,随着等级升高不再推荐低等级玩家 3、玩家等级需要培养,培养需要道具,道具需要看广告/完成任务/付费 4、…...

细说 Java 集合之 Map

前言:本文基于JDK8 一、HashMap 1.1、hash方法 hash方法是map中的基石,后续很多操作都依赖hash方法; 下面是 jdk 7 中 hash方法,注意hashSeed 这个扰动因子,该值随机,所以同一个 key 每次调用hash方法后…...

【vue-echarts】——05.柱状图

文章目录 一、柱状图基本设置1.实现代码2.结果展示二、柱状图效果实现11.代码实现2.结果展示三、柱状图效果实现21.代码实现2.结果展示一、柱状图基本设置 柱状图:一种图表类型,因为构成是由一根一根类似柱子的数据条组合而成的坐标平面,所以命名为柱状 图。主要是用来反应对…...

【C】链式二叉树算法题1 -- 单值二叉树

leetcode链接https://leetcode.cn/problems/univalued-binary-tree/description/ 1 题目描述 如果二叉树每个节点都具有相同的值,那么该二叉树就是单值二叉树。只有给定的树是单值二叉树时,才返回 true;否则返回 false。 示例 1&#xff1…...

C++11——智能指针和function库

目录 一、智能指针 1. std::unique_ptr(独占所有权指针) 2. std::shared_ptr(共享所有权指针) 3. std::weak_ptr(弱引用指针) 关键区别总结 最佳实践 基本用法 可封装的对象类型 核心特性 示例代码…...

[操作系统] 文件的软链接和硬链接

文章目录 引言硬链接(Hard Link)什么是硬链接?硬链接的特性硬链接的用途 软链接(Symbolic Link)什么是软链接?软链接的特性软链接的用途 软硬链接对比文件的时间戳实际应用示例使用硬链接节省备份空间用软链…...

RabbitMQ面试题及原理

RabbitMQ使用场景: 异步发送(验证码、短信、邮件…)MYSQL和Redis, ES之间的数据同步分布式事务削峰填谷 1. 消息可靠性(不丢失) 消息丢失场景: RabbitMQ-如何保证消息不丟失? 开启生产者确…...

SpringBoot中Get请求和POST请求接收参数详解

1、Get请求 1.1 方法形参接收参数 这种方式一般适用参数比较少的情况,并且前后端参数名称必须保持一致 RestController RequestMapping(“/user”) Slf4j public class DemoController { GetMapping("/query") public void getStudent(String name,Strin…...

分布式日志和责任链路

目录 日志问题 责任链问题 分布式日志 GrayLog简介 部署安装 收集日志 配置Inputs 集成微服务 日志回收策略 搜索语法 搜索语法 自定义展示字段 日志统计仪表盘 创建仪表盘 链路追踪 APM 什么是APM 原理 技术选型 Skywalking简介 部署安装 微服务探针 整合…...

h5 IOS端渐变的兼容问题 渐变实现弧形效果

IOS端使用渐变的时候有兼容问题 以下是问题效果,图中黑色部分期望的效果应该是白色的。但是ios端是下面的样子…… 安卓pc 支持: background-image: radial-gradient(circle 40rpx at 100% 0, #f3630c 40rpx, rgb(255, 255, 255) 50%);安卓pc ios支持…...

哈希算法--猜数字游戏

1.题目要求 输入两个位数相同的数,判断对应位置的数字是否相等,返回两个数。第一个数是数字和位置完全猜对的数字个数,第二个数是数字大小猜对但位置不对的数字个数 2.逐步编程 2.1 定义函数 def g(secret,guess):sec_dic{}gue_dic{}# 定义…...

idea生成自定义Maven原型(archetype)项目工程模板

一、什么是Maven原型(Maven archetype) 引自官网的介绍如下: Maven原型插件官网地址 这里采用DeepSeek助手翻译如下: Maven 原型 什么是原型? 简而言之,原型是一个 Maven 项目模板工具包。原型被定义为一…...

Redis面试常见问题——使用场景问题

目录 Redis面试常见问题 如果发生了缓存穿透、击穿、雪崩,该如何解决? 缓存穿透 什么是布隆过滤器? 缓存击穿 缓存雪崩 双写一致性(redis做为缓存,mysql的数据如何与redis进行同步呢?) …...

样式和ui(待更新)

element-plus 先在项目下执行安装语句执行按需导入的命令按照官方文档修改vitest.json sass样式定制 npm -i sass -D在项目下准备定制的样式文件 styles/element/index.scss(!注意这里是.scss文件在vitest.json 修改配置文件 Components({resolvers: [ElementPlusResolver(…...

大摩闭门会:250228 学习总结报告

如果图片分辨率不足,可右键图片在新标签打开图片或者下载末尾源文件进行查看 本文只是针对视频做相应学术记录,进行学习讨论使用...

线程(Thread)

一、概念 线程:线程是一个轻量级的进程 二、线程的创建 1、线程的空间 (1)进程的空间包括:系统数据段、数据段、文本段 (2) 线程位于进程空间内部 (3) 栈区独享、与进程共享文本段、…...

AI军备竞赛2025:GPT-4.5的“情商革命”、文心4.5的开源突围与Trae的代码革命

AI军备竞赛2025:GPT-4.5的“情商革命”、文心4.5的开源突围与Trae的代码革命 ——一场重塑人类认知边界的技术战争 一、OpenAI的“感性觉醒”:GPT-4.5的颠覆与争议 1.1 从“冷面学霸”到“温柔导师”:AI的情商跃迁 当用户输入“朋友放鸽子&…...

DeepSeek + 自由职业 发现新大陆,从 0 到 1 全流程跑通商业 IP

DeepSeek 自由职业 发现新大陆,从 0 到 1 全流程跑通商业 IP 商业定位1. 商业定位分析提示词2. 私域引流策略提示词3. 变现模型计算器提示词4. 对标账号分析提示词5. 商业IP人设打造提示词6. 内容选题策略提示词7. 用户人群链分析提示词8. 内容布局与转化路径设计提…...

基于ASP.NET+ SQL Server实现(Web)医院信息管理系统

医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上,开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识,在 vs 2017 平台上,进行 ASP.NET 应用程序和简易网站的开发;初步熟悉开发一…...

23-Oracle 23 ai 区块链表(Blockchain Table)

小伙伴有没有在金融强合规的领域中遇见,必须要保持数据不可变,管理员都无法修改和留痕的要求。比如医疗的电子病历中,影像检查检验结果不可篡改行的,药品追溯过程中数据只可插入无法删除的特性需求;登录日志、修改日志…...

IT供电系统绝缘监测及故障定位解决方案

随着新能源的快速发展,光伏电站、储能系统及充电设备已广泛应用于现代能源网络。在光伏领域,IT供电系统凭借其持续供电性好、安全性高等优势成为光伏首选,但在长期运行中,例如老化、潮湿、隐裂、机械损伤等问题会影响光伏板绝缘层…...

深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南

🚀 C extern 关键字深度解析:跨文件编程的终极指南 📅 更新时间:2025年6月5日 🏷️ 标签:C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言🔥一、extern 是什么?&…...

高防服务器能够抵御哪些网络攻击呢?

高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...

Java 二维码

Java 二维码 **技术&#xff1a;**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...

用机器学习破解新能源领域的“弃风”难题

音乐发烧友深有体会&#xff0c;玩音乐的本质就是玩电网。火电声音偏暖&#xff0c;水电偏冷&#xff0c;风电偏空旷。至于太阳能发的电&#xff0c;则略显朦胧和单薄。 不知你是否有感觉&#xff0c;近两年家里的音响声音越来越冷&#xff0c;听起来越来越单薄&#xff1f; —…...

JavaScript 数据类型详解

JavaScript 数据类型详解 JavaScript 数据类型分为 原始类型&#xff08;Primitive&#xff09; 和 对象类型&#xff08;Object&#xff09; 两大类&#xff0c;共 8 种&#xff08;ES11&#xff09;&#xff1a; 一、原始类型&#xff08;7种&#xff09; 1. undefined 定…...

Xela矩阵三轴触觉传感器的工作原理解析与应用场景

Xela矩阵三轴触觉传感器通过先进技术模拟人类触觉感知&#xff0c;帮助设备实现精确的力测量与位移监测。其核心功能基于磁性三维力测量与空间位移测量&#xff0c;能够捕捉多维触觉信息。该传感器的设计不仅提升了触觉感知的精度&#xff0c;还为机器人、医疗设备和制造业的智…...

Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析

Java求职者面试指南&#xff1a;Spring、Spring Boot、Spring MVC与MyBatis技术解析 一、第一轮基础概念问题 1. Spring框架的核心容器是什么&#xff1f;它的作用是什么&#xff1f; Spring框架的核心容器是IoC&#xff08;控制反转&#xff09;容器。它的主要作用是管理对…...