数据结构进阶之堆

今天我们学习的是数据结构里面的,大家先看看我们今天要学习的内容

一、堆概念及认识

在学习堆之前我们得先明白完全二叉树是什么样子,因为堆是依据完全二叉树的结构来实现的,所以在这里我先告诉大家完全二叉树的是什么,如下图:

完全二叉树就是从根节点开始依次往下延伸展开,其他层都是满节点,只有最后一层不同,最后一层可满可不满,但是最后一层必须是从左往右,这就是完全二叉树,也就是堆的逻辑结构。

堆的概念及认识:堆是一种数据结构,分为大堆和小堆,数据从上开始往下排序,上一层的数据如果大于下一层的每个数据,那么它就是大堆,反之就是小堆。

二、堆的结构及操作原理

堆的逻辑结构就是完全二叉树的结构,但是我们要实现自己的堆就需要了解堆的物理结构,它是如何实现对数据的储存的,在这里实现堆我们用数组来实现堆,大家可能会一脸懵,所以接下来我向大家解释为什么用数组来实现。

先看下图来理解:

如果把上层看作父节点,下层看作子节点,再看看它们的的数组下标大家会不会发现父子节点之间存在某种关系,这也是其他大佬发现的规律,在这里我直接告诉大家,用 parent 作为父节点的下标,child 作为子节点的下标,就会有下面的下标规律

child = 2 * parent + 1 ,parent = (child - 1)/  2 。

因为有上面的规律,所以我们实现自己的堆才选择用数组来储存,上面的规律也是堆实现的底层逻辑。

三、堆的实现

在这里我们以实现小堆为例,首先我得先告诉大家小堆的储存结构,大家先看下图:

如果是小堆,那么上一层的数据必须小于下一层的数据,并且最高层的数据是最小的,这就是小堆。那么接下来我们就来实现一个自己的堆。

首先需要创建一个结构体用来储存堆的数组和堆的大小和堆的数据个数,如下:

typedef int HPDataType;
typedef struct Heap
{HPDataType* a;// 堆的物理结构时数组,逻辑结构是满二叉树或完全二叉树int size;int capacity;
}HP;

接下来我们先写出最简单的堆的初始化和销毁和一个交换函数,如下:

//堆的初始化
void HPInit(HP* hp)
{assert(hp);hp->a = NULL;hp->capacity = hp->size = 0;
}//堆的销毁
void HPDestroy(HP* hp)
{assert(hp);free(hp->a);hp->capacity = hp->size = 0;
}//实现交换数据
void Swap(HPDataType* hp1, HPDataType* hp2)
{HPDataType tem = *hp1;*hp1 = *hp2;*hp2 = tem;
}

最难的部分就是堆数据放入时的向上调整,因为是小堆,所以上一层的数据必须小于下一层的每个数据,所以每次放进一个数据就要向上进行调整,用来保证小堆的结构,那如何来实现数据的想上调整呢,请看下面:

根据上面的讲解我们开始实现向上调整,请结合代码中的注释加以理解:

//堆数据的向上调整 时间复杂度:O(logN)
void AdjustUp(HP* hp, int child)
{assert(hp);assert(hp->size > 0);// 截至条件是 当最后一次的子节点小于或者等于0的时候 说明上层没有数据 也就不用再向上调整了while (child > 0){// 实现数据的交换// 根据父子的关系规律来找到父节点int parent = (child - 1) / 2;if (hp->a[parent] > hp->a[child]){//交换Swap(&(hp->a[parent]), &(hp->a[child]));child = parent;}else{// 如果已经符合小堆 就直接退出break;}}
}

有了上面的向上调整,我们就可以开始实现数据的入队列了,操作如下:

//堆的放入数据
void HPPush(HP* hp, HPDataType x)
{assert(hp);if (hp->capacity == hp->size){// 堆内存的开辟int newcapacity = hp->capacity == 0 ? 4 : 2 * hp->capacity;HPDataType* tem = (HPDataType*)realloc(hp->a, sizeof(HPDataType) * newcapacity);if (tem == NULL){perror("realloc");exit(1);}hp->a = tem;hp->capacity = newcapacity;}// 堆数据的放入hp->a[hp->size] = x;hp->size++;// 每次放入一个数据都需要进行向上调整来保证小堆的完整性AdjustUp(hp, hp->size - 1);
}

接下来我们继续实现堆的其他简单操作,如下:

//获取堆顶数据
HPDataType HPTop(HP* hp)
{assert(hp);return hp->a[0];
}//堆中的数据个数
int HPSize(HP* hp)
{assert(hp);return hp->size - 1;
}//堆的判空
bool HPEmpty(HP* hp)
{assert(hp);return hp->size == 0;
}

 接下来还有一个难点就是堆顶数据的删除,首先我们得了解一下堆顶数据是如何进行删除的,我来告诉大家,堆顶数据的删除不是真的删除,而是把堆顶的数据和堆的最后一位数据进行交换,并且对堆顶的数据再进行向下调整,来保证小堆的结构。上面我有提到了向下调整,这其实和向上调整一样,请大家看原理图:

那为什么要和两个子节点中较小的进行比较呢,因为要符合小堆,必须最高层数据是最小值,所以要和两个子节点中较小的进行比较,实现如下请结合注释一起理解:

//堆数据的向下调整 时间复杂度:logN
void AdjustDown(HP* hp, int parent)
{assert(hp);// 用父子节点之间的规律来找到子节点int child = 2 * parent + 1;// 退出条件为 最后一次的子节点超出堆的大小就不用在进行向下调整 直接退出循环while (child < hp->size){// 要判断两个子节点中的最小值 首先这个父节点下面要有两个子节点才可以 如果没有就直接和子节点比较饥渴if (child + 1 < hp->size){if (hp->a[child] > hp->a[child + 1]){// 假设法选出两个儿子中的最小值child = child + 1;}}if (hp->a[parent] > hp->a[child]){// 交换两个值Swap(&(hp->a[child]), &(hp->a[parent]));parent = child;child = 2 * parent + 1;}else{// 如果没有交换 说明满足小堆的结构 直接退出即可break;}}}

接下来堆顶数据的删除就可以结合堆顶数据的删除原则(如堆顶数据删除的原理图)就可以写出来了,如下:

//堆顶数据的删除
void HPPop(HP* hp)
{assert(hp);Swap(&(hp->a[0]), &(hp->a[hp->size - 1]));hp->size--;AdjustDown(hp, 0);
}

这就是堆的实现,大家还有什么不会的或者没理解的,可以评论区留言或者私信我,我来帮大家解答。

好了,今天的内容就到这,下期再见!!!

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

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

相关文章

Excel中输入数字会改变怎么办?

一、数字显示不全&#xff0c;以“#”号代替 随着列宽的缩小&#xff0c;数字逐渐被“#”号代替&#xff08;首先数字的格式是“数值型&#xff0c;且只有整数”&#xff09; 原因分析&#xff1a;单元格中的数字无法完全显示&#xff0c;Excel会自动用“#”号填充剩余的空间 解…

00_如何使用国内镜像源下载QT

如何使用国内镜像源下载QT 如何使用国内镜像源下载QT 如何使用国内镜像源下载QT 第一步&#xff1a;下载下载qt online installer 网站&#xff1a;https://download.qt.io/official_releases/online_installers/ 添加链接描述 下载windows版本 第二步&#xff1a; 剪切放…

搭建个人智能家居 4 -WS2812B-RGB灯

搭建个人智能家居 4 - WS2812B-RGB灯 前言说明ESPHomeHomeAssistant 前言 上一篇文章我们已经完成了第一个外设的添加&#xff08;一个LED灯&#xff09;&#xff0c;今天接着来“壮大”这个系统&#xff0c;添加第二个外设“RGB灯”。 环境搭建可以回顾前面的文章。前文回顾&…

AutoCAD 2024 安装注册教程

前言 大家好&#xff0c;我是梁国庆。 本篇分享的安装包是 AutoCAD 的全新版本——AutoCAD 2024&#xff0c;下文安装教程中简称 AutoCAD。 时间&#xff1a;2024年4月8日。 获取 AutoCAD 安装包 我已将本篇所使用的安装包打包上传至百度云&#xff0c;扫描下方二维码关注…

Linux 内核学习(1) --- 时钟子系统

标题 时钟系统说明时钟树Clock Provider时钟通用数据结构clock_device 的注册clock_provider DTS配置和注册clock consumer时钟系统总结 时钟系统说明 时钟就是 SoC 中的脉搏&#xff0c;由它来控制各个部件按各自的节奏跳动。比如&#xff0c;CPU主频设置&#xff0c;串口的波…

windows本地运行dreamtalk踩坑总结

dreamtalk是一个语音图片转视频的一个工具&#xff0c;就是给一段语音加一个头像图片&#xff0c;然后生成一段头像跟语音对口型的视频&#xff0c;其实还是很有意思的&#xff0c;最近阿里发布了一个类似的模型&#xff0c;但是还没开源&#xff0c;从展示视频看&#xff0c;阿…

itext7 pdf转图片

https://github.com/thombrink/itext7.pdfimage 新建asp.net core8项目&#xff0c;安装itext7和system.drawing.common 引入itext.pdfimage核心代码 imageListener下有一段不安全的代码 unsafe{for (int y 0; y < image.Height; y){byte* ptrMask (byte*)bitsMask.Scan…

Centos 7.9.2009 下 Gitlab 完全卸载

一、linux版本&#xff1a;lsb_release -a 二、GtiLab 版本 # 查看gitlab的版本号 cat /opt/gitlab/embedded/service/gitlab-rails/VERSION 三、开始卸载 3.1&#xff0c;停止Gitlab 相关服务 # 停止所有GitLab相关服务&#xff1a; sudo gitlab-ctl stop# 移除GitLab包…

【2024年MathorCup数模竞赛】C题完整解析(代码与技术文档)

C题第一问 1 数据预处理2 问题一2.1基于混合ARIMA-LSTM预测模型的未来30天货量预测2.1.1 自适应混合ARIMA-LSTM混合预测模型的建立2.1.2 自适应混合ARIMA-LSTM混合预测模型的求解 2.2 基于混合ARIMA-LSTM预测模型与模糊修正的未来30天每小时货量预测 代码分享 目前已经完成C题数…

如何利用python机器学习解决空间模拟与时间预测问题

徐老师&#xff1a;副教授&#xff1a;长期从事定量遥感、遥感数据同化、地表水热通量转化等相关领域的研究&#xff0c;发表多篇相关领域核心期刊论文&#xff0c;具有丰富的实践技术经验。 专题一、机器学习原理与概述 了解机器学习的发展历史、计算原理、基本定义&#xf…

vue快速入门(二十一)计算属性

注释很详细&#xff0c;直接上代码 上一篇 新增内容 计算属性的基本应用 源码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.…

Springboot+Vue项目-基于Java+MySQL的社区团购系统(附源码+演示视频+LW)

大家好&#xff01;我是程序猿老A&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;Java毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计 &…

酷得智能 无人机方案开发

东莞市酷得智能科技有限公司&#xff0c;是一家专业的技术服务公司&#xff0c;致力于为各类智能硬件提供高效、稳定、安全的底层驱动解决方案。拥有一支经验丰富、技术精湛的团队&#xff0c;能够为客户提供全方位的底层驱动开发服务。 无人机功能介绍&#xff1a; 1、自动跟…

【前缀合】Leetcode 连续数组

题目解析 525. 连续数组 寻找一个子数组&#xff0c;这个子数组中包含相同数目的0和1&#xff0c;但是这个子数组需要最长的 算法讲解 只需在[0,i]寻找一段区间使得这一段区间的和也等于sum即可 细节问题&#xff1a;1. 这里的哈希表的value存的是下标&#xff0c;因为需要找…

【Java】第十五届蓝桥杯JavaB组第一道填空题

&#xff03;【Java】第十五届蓝桥杯JavaB组第一道填空题 大家好 我是寸铁&#x1f44a; 总结了一篇【Java】第十五届蓝桥杯JavaB组第一道填空题文章 喜欢的小伙伴可以点点关注 &#x1f49d; Java B组 第一道填空题题解如下:

科研学习|科研软件——SPSS统计作图教程:多组折线图(≥3个变量)

一、问题与数据 研究者想研究45-65岁不同性别人群中静坐时长和血胆固醇水平的关系,分别招募50名男性和女性(gender)询问其每天静坐时长(time,分钟),并检测其血液中胆固醇水平(cholesterol, mmol/L),部分数据如图1。研究者该如何绘图展示这两者间的关系呢? 二、问题…

Traefik与传统的Edge Router有何不同?

在云原生时代&#xff0c;传统的网络架构和现代的解决方案之间存在明显的差异。特别是在处理网络流量和路由方面&#xff0c;传统的 Edge Router 与像 Traefik 这样的现代反向代理和负载均衡器相比&#xff0c;展现出许多不同的特点。本文将深入探讨 Traefik 与传统 Edge Route…

YOLO-World: Real-Time Open-Vocabulary Object Detection 简介+安装+运行+训练(持续更新)

前言 YOLO_WORLD太牛了&#xff01;&#xff01;众所周知&#xff0c;传统是视觉目标检测一旦训练好后&#xff0c;如果我们需要增加新的识别目标的话&#xff0c;必须得重新训练模型。在生产中如果经常要新增检测目标&#xff0c;对时效性影响很大&#xff0c;而且随着数据量…

.vue文件引入路径正确,但报错

问题描述 使用Vue挂载组件时&#xff0c;导入路径正确&#xff0c;但是一直提示 Already included file name ‘绝对路径/index.vue’ differs from file name ‘绝对路径/Index. vue’ only in casing. The file is in the program because: Imported via ‘./components/ind…

O2OA开发平台如何查看数据表结构?

在访问后端api地址&#xff0c;页面最下方有列示平台的各个服务&#xff0c;点击进入可查看具体的表内容 后端api地址&#xff1a; http://{hostIP}/x_program_center/jest/list.html 其中&#xff1a;{hostIP}为中心服务器所在域名或者IP地址 如下图&#xff1a;