数据结构:堆的创建和使用

上一期我们学习了树和二叉树的定义,其中我们了解到了两种特殊的二叉树:满二叉树和完全二叉树。

今天我们还要学习一种新的结构:堆

那这种结构和二叉树有什么联系呢???

通过观察我们可以发现,完全二叉树和满二叉树可以看作是一个连续的结构,所以我们可以使用顺序存储,但是这种结构还不算是堆结构,那么堆又和这种结构有什么联系呢???

 下面是两种堆的结构:一种是大堆,一种是小堆

那么什么是大堆和小堆呢?

顾名思义,小堆就是根节点都比孩子结点小的

大堆就是根节点都比孩子结点大的

下面就是两种堆的结构:

  那么我们学习堆有什么意义呢?下面是堆的几种运用场景:

后面我们会有所了解。

 

这里我们先来了解一下堆排序

通过对比我们可以发现,堆排序相比冒泡排序的时间复杂度是远远要好的

下面我们就正式进入堆的学习中。

 我们先来看堆的定义:

因为堆是顺序结构,所以我们定义的方式和顺序表是一致的。

 在实现堆中我们需要使用两种算法,一种是向上调整算法,一种是向下调整算法。

 (假设在小堆中)在向上调整算法中,我们插入50,我们需要将它的值与根节点的值进行比较,

如果比根节点小我们就进行交换。直到我们的孩子结点走到最顶端,也就是下标为0的位置。

 那么我们要怎么寻找每次的孩子结点和父结点的下标呢?

通过观察我们可以发现孩子结点和自己的父结点有以下规律:

 所以每一次结束比较后我们都要将父结点赋值给孩子节点,并让父结点走向当前孩子结点的父结点。所以下面是代码的实现

 所以在堆中我们每次插入数据都需要调整值的顺序。但是,我们思考后会发现,我们的向上和向下调整算法都只能调整父结点和孩子结点的关系,而不能改变兄弟结点的关系

所以我们的堆插入数据的函数如下

 下面我们来写“删除堆顶元素”函数

我们将堆顶元素认为是下标为0所在位置的元素,有一些人就想当然将后面的数据覆盖上去,但是,这一种思路是不对的,我们仔细思考一下,我们这样子做,我们的结点间的父子关系就全都不对了,也就是我们的堆就不是堆了,顺序已经被打乱了

那么我们应该怎么做呢???

这里我们的另一种向调下整算法就起到了重要的作用。

删除时,首先我们将首元素和末尾元素的值交换,之后我们只要将size--就可以删除尾部元素,也就是原来的堆顶的元素,之后我们再将堆顶的元素向下调整。

那么向下调整的算法是怎样书写的呢???

向下调整中,我们定义父结点,之后通过上面的父结点和子节点的关系,我们可以找到左子节点,

左子节点和右子节点下标相差1,我们通过比较左子节点和右子节点的值,我们选出最小的,若此时的父结点的值大于最小的子节点,我们就进行交换,之后一直走循环,直到父结点走到动态数组的最后面

下面是向下调整算法的书写 

 下面是删除堆顶元素的函数:

 其中HPEmpty函数是判断堆是否为空的函数

 到这里我们就可以解决topk问题,比如我们要取出一千万数的前十名,我们就可以返回堆顶元素,之后pop9次就可以了。

这里我们要了解topk问题的具有现实的意义,比如我们在点外卖时,我们要选取销量前十的我们就可以使用topk解决问题

下面是全部代码

void HPInit(HP* php)//初始化堆堆空间
{php->size = 0;php->a = NULL;php->capcity = 0;
}
void swap(int* p1, int* p2)
{int tmp = *p1;*p1 = *p2;*p2 = tmp;
}//交换函数
void AdjustUp(int* a, int Child)
{int child = Child;int parent = (child - 1) / 2;while(child > 0)//直到孩子结点走到下标为0的位置{if (a[child] < a[parent]){swap((a) + child, (a) + parent);//发现子节点的值比父节点小就进行交换child = parent;//将父结点赋值给孩子结点parent = (child - 1) / 2;//走向下一个父结点}else{break;//若孩子结点大就退出循环,即不需要交换}}return;
}
void HPPush(HP* php, HPDatatype x)//插入数据
{if(php->size == php->capcity){int newcapcity = php->capcity == 0 ? 4 :php->capcity * 2;//看空间是否足够HPDatatype* a = (HPDatatype*)realloc(php->a, sizeof(HPDatatype) * newcapcity);if (a == NULL){perror("malloc_fail");return;}php->a = a;php->capcity = newcapcity;}php->a[php->size] = x;php->size++;//开辟新的空间并存放数据AdjustUp(php->a,php->size - 1);//通过向上调整顺序形成小堆
}
bool HPEmpty(HP* php)
{return php->size == 0;
}
void AdjustDown(int* a,int n ,int parent)
{assert(a);int child = parent * 2 + 1;while(child < n){if (child + 1 < n && a[child] > a[child + 1])//选出较小的子节点{child += 1;}if (a[parent] > a[child])//父节点都比两个子节点小就返回{swap(a + parent, a + child);//与较小的子节点交换位置//往下再寻找parent = child;child = parent * 2 + 1;}else{break;//若父结点的值小于最小子节点的值我们就退出循环,即这个堆还是小堆}}
}
void HPPop(HP* php)//删除堆顶元素
{assert(php);assert(!HPEmpty(php));swap(php->a, php->a + php->size - 1);//交换顶部元素和底部元素php->size--;AdjustDown(php->a,php->size,0);//向下调整
}
int HPTop(HP* php)//返回堆顶的元素
{return php->a[0];
}
void HPDestroy(HP* php)//销毁堆空间
{assert(php);free(php->a);php->a = NULL;
}

以上就是本次的全部内容,谢谢大家观看!!!

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

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

相关文章

UE5 C++增强输入

一.创建charactor&#xff0c;并且包含增强输入相关的头文件 1.项目名.build.cs。添加模块“EnhancedInput”&#xff0c;方便找到头文件和映射的一些文件。 PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine&q…

塔楼VR火灾逃生应急安全教育突破了传统模式

城镇化的高速发展&#xff0c;给消防安全带来了严峻的挑战&#xff0c;尤其是人员密集的办公场所&#xff0c;如何预防火灾发生&#xff0c;学习火灾成因&#xff0c;减少火灾发生避免不必要的损失&#xff0c;成为安全应急科普的重中之重。 通过模拟真实的办公场所火灾场景&am…

中国贸易金融跨行交易区块链平台CTFU、区块链福费廷交易平台BCFT、中国人民银行贸易金融区块链平台CTFP、银行函证区块链服务平台BPBC

中国人民银行贸易金融区块链平台CTFP介绍 贸易金融的发展概况及存在的问题 1.1 贸易金融的概况 贸易金融是指商业银行在贸易双方债权债务关系的基础上&#xff0c;为国内或跨国的商品和服务贸易提供的贯穿贸易活动整个价值链、全程全面性的综合金融服务。伴随全球化的进程&a…

【Mock|JS】Mock的get传参+获取参数信息

mockjs的get传参 前端请求 const { data } await axios("/video/childcomments", {params: {sort: 1,start: 2,count: 5,childCount: 6,commenIndex: 0,},});后端获取参数 使用正则匹配url /*** # 根据url获取query参数* param {Url} urlStr get请求获取参数 eg:…

inputStream.avaliable()方法网络操作读取不全BUG

一、问题描述 公司有个需求&#xff0c;就是调用方&#xff08;我&#xff09;需要把pdf文件转为Base64字符串作为参数传递为被调用方&#xff0c;以下是大致转换过程&#xff1a; URL url new URL("http://xxxx.pdf");HttpURLConnection uc (HttpURLConnection) …

HTML(一)

一、网页 1.1 什么是网页 网站是指在因特网上根据一定的规则&#xff0c;使用 HTML 等制作的用于展示特定内容相关的网页集合。 网页是网站中的一“页”&#xff0c;通常是 HTML 格式的文件&#xff0c;它要通过浏览器来阅读。 网页是构成网站的基本元素&#xff0c;它通常由…

ByteMD - 掘金社区 MarkDown 编辑器的免费开源的版本,可以在 Vue / React / Svelte 中使用

各位元宵节快乐&#xff0c;今天推荐一款字节跳动旗下掘金社区官方出品的 Markdown 编辑器 JS 开发库。 ByteMD 是一个用于 web 开发的 Markdown 编辑器 JavaScript 库&#xff0c;是字节跳动&#xff08;也就是掘金社区&#xff09;出品的 Markdown 格式的富文本编辑器&#…

ModbusRTU/TCP/profinet网关在西门子博图软件中无法连接PLC的解决方法

ModbusRTU/TCP/profinet网关在西门子博图软件中无法连接PLC的解决方法 在工业生产现场&#xff0c;ModbusRTU/TCP/profinet网关在与西门子PLC连接时&#xff0c;必须要使用西门子的博图软件来进行配置&#xff0c;博图v17是一个集成软件平台&#xff0c;专业版支持300、400、12…

【机器学习】基于正余弦搜索算法优化的BP神经网络分类预测(SCA-BP)

目录 1.原理与思路2.设计与实现3.结果预测4.代码获取 1.原理与思路 【智能算法应用】智能算法优化BP神经网络思路【智能算法】正余弦优化算法&#xff08;SCA&#xff09;原理及实现 2.设计与实现 数据集&#xff1a; 多输入多输出&#xff1a;样本特征24&#xff0c;标签类…

利用Python进行数据清洗与预处理:Pandas的高级用法【第147篇—Pandas的高级用法】

&#x1f47d;发现宝藏 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。【点击进入巨牛的人工智能学习网站】。 利用Python进行数据清洗与预处理&#xff1a;Pandas的高级用法 在数据科学和机器学习领域&…

【Linux】调试器-gdb的使用说明(调试器的配置,指令说明,调试过程说明)

目录 00.背景 01.安装 02.生成调试信息 03.调试过程 00.背景 在软件开发中&#xff0c;通常会为程序构建两种不同的版本&#xff1a;Debug模式和Release模式。它们之间的区别主要在于优化级别、调试信息、错误检查等方面&#xff1a; 1.Debug 模式&#xff1a; 优化级别低…

使用uni-app框架进行移动端的适配(uniapp px转rpx)

1、打开uniapp 官网找到 插件市场介绍2、点击插件市场 px2rpx - DCloud 插件市场3、选择使用HBuilderX导入插件4、在HBuilder中点击右键选择开启px2rpx 5、开启成功后会有提示 6、根据设计搞的尺寸就行&#xff0c;我的是在这750*1620的&#xff0c;正常写px&#xff0c;保存…

[音视频学习笔记]六、自制音视频播放器Part1 -新版本ffmpeg,Qt +VS2022,都什么年代了还在写传统播放器?

前言 参考了雷神的自制播放器项目&#xff0c;100行代码实现最简单的基于FFMPEGSDL的视频播放器&#xff08;SDL1.x&#xff09; 不过老版本的代码参考意义不大了&#xff0c;我现在准备使用Qt VS2022 FFmpeg59重写这部分代码&#xff0c;具体的代码仓库如下&#xff1a; …

ubuntu20.04搭建nginx rtmp视频服务到指定位置解决权限不足

1.安装依赖 apt-get install build-essential libpcre3 libpcre3-dev libssl-dev2.建一个目录 mldir rtmp_nginx 3.源码下载 wget http://nginx.org/download/nginx-1.21.6.tar.gz wget https://github.com/arut/nginx-rtmp-module/archive/master.zip4.解压缩 tar -xf ng…

https 协议

什么是 Https 协议 HTTPS 也是⼀个应⽤层协议. 是在 HTTP 协议的基础上引⼊了⼀个加密层。HTTP 协议内容都是按照⽂本的⽅式明⽂传输的. 这就导致在传输过程中出现⼀些被篡改的情况。HTTPS 通过使用协议加密通信&#xff0c;可以保护数据在传输过程中的安全性&#xff0c;防止…

前端vue2如何处理Rss订阅、聚合,前端 vue2 如何处理xml 格式的数据

文章目录 前言解决 前言 最近看见csdn有Rss订阅这个功能&#xff0c;但发现这个接口响应的数据格式不是常用的Json格式而是xml&#xff0c;即下图的格式。 附响应的代码 <?xml version"1.0" encoding"utf-8" ?><rss version"2.0"&g…

微软开源Garnet高性能缓存服务安装

Garnet介绍 Garnet是一款微软研究院基于C#开发而开源的高性能缓存服务&#xff0c;支持Windows、Linux多平台部署&#xff0c;Garnet兼容Redis服务API&#xff0c;在性能和使用架构上较Redis有很大提升&#xff08;官方说法&#xff09;&#xff0c;并提供与Redis一样的命令操…

UE5的渲染-太难了

大家可以看到&#xff0c;这些都是UE的渲染&#xff0c;非常漂亮惊叹&#xff0c;渲染已经非常成熟&#xff0c;这些画面并不是离线渲染&#xff0c;而是实时渲染。早先年我们渲染CG动画都采用离线渲染&#xff0c;要用到庞大的渲染农场&#xff0c;每渲染一帧都可能需要半个小…

WebGIS航线编辑器(无人机航线规划)

无人机航点、航线规划&#xff0c;实现全自动航点飞行作业及飞行航拍。禁飞区、作业区功能保障飞行安全。 GIS引擎加载 const viewer new Cesium.Viewer("cesiumContainer", { imageryProvider: new Cesium.IonImageryProvider({ assetId: 3872 }), }); const im…

【Django实战一】创建新项目

一、新建Project django-admin startproject 项目名称二、创建应用 1、创建应用 python manage.py startapp 应用名称应用创建后&#xff0c;项目的根目录下会生成对应应用名称的文件夹 2、注册应用 新创建的应用需要在settings.py中的INSTALLED_APPS中注册该应用 INSTALL…