[C/C++]数据结构 堆的详解

一:概念

        堆通常是一个可以被看做一棵完全二叉树的数组对象,它是一颗完全二叉树,堆存储的所有元素按完全二叉树的顺序存储方式存储在一个一维数组中,并且需要满足每个父亲结点总小于其子节点(或者每个父亲结点总大于其子节点)

        堆可以分为两种:

  • 小堆: 任意一个父亲节点都小于其子节点
  • 大堆:任意一个父亲节点都大于其子节点

二:堆的定义

       堆是一个完全二叉树,但是其物理逻辑为数组

typedef int HPDataType;
typedef struct heap
{HPDataType* a;int size;      int capacity;  //数组容量
}HP;

 接口:

//堆的初始化
void InitHeap(HP* hp);//在堆上入一个数据使其还是堆
void HeapPush(HP* hp, HPDataType x);//在堆上出一个数据使其还是堆
void HeapPop(HP* hp);//取堆头元素
HPDataType HeapTop(HP* hp);//判断堆是否为空
bool HeapEmpty(HP* hp);//求堆的长度
int HeapSize(HP* hp);//堆的销毁
void DestoryHeap(HP* hp);

三:接口实现

        堆的实现许多操作和顺序表的实现相同,忘记顺序表的烙铁可以复习一下顺序表-->[C/C++]数据结构----顺序表的实现(增删查改) ,我们以小堆的实现为例:

1.堆的初始化

void InitHeap(HP* hp)
{hp->a = NULL;hp->size = 0;hp->capacity = 0;
}

2.判断堆是否为空

bool HeapEmpty(HP* hp)
{assert(hp);return hp->size == 0;
}

3.堆的销毁

void DestoryHeap(HP* hp)
{assert(hp);free(hp->a);hp->size = 0;hp->capacity = 0;
}

4.返回堆头元素

HPDataType HeapTop(HP* hp)
{assert(hp);assert(hp->size);return hp->a[0];
}

5.堆的大小

int HeapSize(HP* hp)
{assert(hp);return hp->size;
}

到重点啦!!!

ps:下面的向下和向上调整法都是按小堆实现的,若要按大堆实现只需改下大小比较符号即可

6.入堆(在堆里面插入一个数据,使其还是堆)

      先将数据插入到堆的末尾,如果堆的性质被破坏的话,就让该节点与其父亲结点交换,向上调整,直到满足堆的性质

        例如:在小堆后面插入数据10

由于10小于他的父亲结点,所以应该让10和其父亲结点交换

此时10仍然小于其父亲节点,继续交换

仍然不满足堆的性质,继续交换

向上调整完成

这些数据的存储逻辑上堆为二叉树结构,实际上数据储存在数组中,向上调整法涉及到了如何通过孩子结点找到双亲结点,其实这里有一些结论可以通过一方的下标找到另一方的下标

  • parent = (child-1)/2
  • leftchild = parent*2+1
  • rightchild = parent*2+2

        向上调整法代码实现:

void AdjustUP(HP* hp, int child)
{int parent = (child - 1) / 2;while (child > 0) //最坏的情况就是需要调整到下标为0的位置{if (hp->a[parent] > hp->a[child]){swap(&hp->a[parent], &hp->a[child]);child = parent;parent = (parent - 1) / 2;}else{//由于插入数据前本来就是堆,如果不满足上述条件,说明所有数据已经满足堆的性质了break;}}
}

入堆:

void HeapPush(HP* hp, HPDataType x)
{assert(hp);//判断是否需要扩容if (hp->size == hp->capacity){int newcapacity = hp->capacity == 0 ? 4 : hp->capacity * 2;HPDataType* ret = (HPDataType*)realloc(hp->a, sizeof(HPDataType) * newcapacity);if (ret == NULL){perror("realloc");exit(-1);}hp->a = ret;hp->capacity = newcapacity;}//尾插数据hp->a[hp->size] = x;hp->size++;//向上调整AdjustUP(hp, hp->size - 1);
}

7.堆的删除

        堆的删除默认是删除堆顶的元素,如果直接删除堆顶的元素,再将其孩子结点中较小的结点作为堆顶的话,会导致大小关系错乱,因为本来堆顶的左右子树就是堆,按刚刚讲的方法,其堆结构就会被破坏,还需要重新建堆调整,这样的消耗太大了,相反,如果删除一个堆尾的元素消耗却很小,所以可以按如下方法:

  1. 把堆顶元素和堆尾元素交换
  2. 删除堆尾元素
  3. 将堆头元素向下调整到合适位置

向下调整法代码实现:

void AdjustDown(HPDataType* a, int size, int parent)
{//这里假设左孩子是两孩子里面较大的HPDataType child = parent * 2 + 1;while (child<size){    //验证假设是否成立,不成立则更新孩子结点//右边的条件是为了排除数组访问越界的情况,child+1是右孩子下标if (a[child + 1] < a[child] && (child + 1) < size){child = child + 1;}//如果父亲结点比孩子结点大,交换if (a[parent] > a[child]){swap(&a[parent], &a[child]);parent = child;child = child * 2 + 1;}else{break;}}
}

堆得删除:

void HeapPop(HP* hp)
{assert(hp);swap(&hp->a[0], &hp->a[hp->size - 1]);hp->size--;AdjustDown(hp->a, hp->size, 0);
}

四:效果展示

heap.h  :用于结构的定义和函数的声明


#pragma once	
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>typedef int HPDataType;
typedef struct heap
{HPDataType* a;int size;int capacity;
}HP;void InitHeap(HP* hp);
void HeapPush(HP* hp, HPDataType x);
void HeapPop(HP* hp);
HPDataType HeapTop(HP* hp);
bool HeapEmpty(HP* hp);
int HeapSize(HP* hp);
void DestoryHeap(HP* hp);

heap.c: 用于函数的实现

#define  _CRT_SECURE_NO_WARNINGS 1		
#include"heap.h"void InitHeap(HP* hp)
{hp->a = NULL;hp->size = 0;hp->capacity = 0;
}void DestoryHeap(HP* hp)
{assert(hp);free(hp->a);hp->size = 0;hp->capacity = 0;
}void swap(HPDataType* a, HPDataType* b)
{HPDataType tmp = *a;*a = *b;*b = tmp;
}void AdjustUP(HP* hp, int child)
{int parent = (child - 1) / 2;while (child > 0){if (hp->a[parent] > hp->a[child]){swap(&hp->a[parent], &hp->a[child]);child = parent;parent = (parent - 1) / 2;}else{break;}}
}void HeapPush(HP* hp, HPDataType x)
{assert(hp);if (hp->size == hp->capacity){int newcapacity = hp->capacity == 0 ? 4 : hp->capacity * 2;HPDataType* ret = (HPDataType*)realloc(hp->a, sizeof(HPDataType) * newcapacity);if (ret == NULL){perror("realloc");exit(-1);}hp->a = ret;hp->capacity = newcapacity;}hp->a[hp->size] = x;hp->size++;AdjustUP(hp, hp->size - 1);
}HPDataType HeapTop(HP* hp)
{assert(hp);assert(hp->size);return hp->a[0];
}bool HeapEmpty(HP* hp)
{assert(hp);return hp->size == 0;
}int HeapSize(HP* hp)
{assert(hp);return hp->size;
}void AdjustDown(HPDataType* a, int size, int parent)
{HPDataType child = parent * 2 + 1;while (child<size){if (a[child + 1] < a[child] && (child + 1) < size){child = child + 1;}if (a[parent] > a[child]){swap(&a[parent], &a[child]);parent = child;child = child * 2 + 1;}else{break;}}
}void HeapPop(HP* hp)
{assert(hp);swap(&hp->a[0], &hp->a[hp->size - 1]);hp->size--;AdjustDown(hp->a, hp->size, 0);
}

test.c :测试功能

#define  _CRT_SECURE_NO_WARNINGS 1		
#include"heap.h"
int main()
{int a[] = { 9,8,7,6,5,4,3,2,1 };HP hp;InitHeap(&hp);//这里是将数组的数据依次插入形成堆for (int i = 0; i < sizeof(a) / sizeof(int); i++){HeapPush(&hp, a[i]);}//依次打印堆头元素while (!HeapEmpty(&hp)){printf("%d ", HeapTop(&hp));HeapPop(&hp);}return 0;
}

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

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

相关文章

AIGC创作系统ChatGPT网站源码、支持最新GPT-4-Turbo模型、GPT-4图片对话能力+搭建部署教程

一、AI创作系统 SparkAi创作系统是基于ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统&#xff0c;支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美&#xff0c;可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如何搭建部署AI…

HarmonyOS应用开发者基础认证【满分答案】

系列文章 HarmonyOS应用开发者基础认证【闯关习题 满分答案】 HarmonyOS应用开发者基础认证【满分答案】 HarmonyOS云开发基础认证【最新题库 满分答案】 目录 系列文章一、判断题二、单选题三、多选题 一、判断题 在Column和Row容器组件中&#xff0c;justifyContent用于设置…

常见树种(贵州省):022绣线菊、月月青、金合欢、胡枝子、白刺花

摘要&#xff1a;本专栏树种介绍图片来源于PPBC中国植物图像库&#xff08;下附网址&#xff09;&#xff0c;本文整理仅做交流学习使用&#xff0c;同时便于查找&#xff0c;如有侵权请联系删除。 图片网址&#xff1a;PPBC中国植物图像库——最大的植物分类图片库 一、绣线菊…

100天精通Python(可视化篇)——第109天:Pyecharts绘制各种常用地图(参数说明+代码实战)

文章目录 专栏导读一、地图应用场景二、参数说明1. 导包2. add函数 三、地图绘制实战1. 省市地图2. 中国地图3. 中国地图&#xff08;带城市&#xff09;4. 中国地图&#xff08;分段型&#xff09;5. 中国地图&#xff08;连续型&#xff09;6. 世界地图7. 行程轨迹地图8. 人口…

WebUI自动化学习(Selenium+Python+Pytest框架)001

开启另一篇学习之路_WebUI自动化 先来一波基础概念 1.自动化适合什么类型的项目: 重复性高,迭代频率高的回归测试。数据量大、手工难以实现的压力测试&#xff0c;手工执行效率低的兼容测试 2.自动化的优点: 高效率、可重复、减少人为错误、克服手工测试的局限性 3.自动化…

光线追踪-Peter Shirley的RayTracingInOneWeekend系列教程(book1-book3)代码分章节整理

自己码完了一遍了&#xff0c;把代码分章节整理了一下&#xff0c;可以按章节独立编译&#xff0c;运行, 也可以直接下载编译好的release版本直接运行。 项目地址&#xff1a; Github: https://github.com/disini/RayTracingInOneWeekendChaptByChapt ​ ​ ​ ​

Rust语言入门教程(八) - 引用与借用

上一章的内容中我们讨论了Rust的所有权系统&#xff0c;当我们不想移动值的所有权时&#xff0c;我们可以使用引用和借用&#xff0c;而这正是本章想要讨论的问题。 引用&#xff08;References&#xff09; 引用允许你访问或修改数据而无需获取数据的所有权。在 Rust 中&…

阿里云MQTT: 子设备上线流程

0. 背景 阿里云网关子设备上平台的资料很少。有些厂家直接配置每个子设备的DeviceSecret到网关里&#xff0c;显然太麻烦了&#xff01;我经过阅读阿里文档&#xff0c;发现有些简化的方法&#xff0c;更便于客户使用&#xff0c;因此分享给大家。 1. 主要信息片段 子设备 $…

基于springboot+mysql实现的小区物业管理系统

基于springbootmysql实现的小区物业管理系统,演示地址:登录 演示账号&#xff1a;用户名:744621980qq.com 密码:123456,主要包含房屋管理(楼栋管理&#xff0c;单元管理&#xff0c;房屋管理)&#xff0c;车位管理&#xff0c;缴费管理&#xff0c;社区服务( 公告管理&#xf…

Linux socket编程(6):IO复用之select原理及例子

文章目录 1 五种I/O模型1.1 阻塞I/O模型1.2 非阻塞I/O模型1.3 I/O复用模型1.4 信号驱动I/O模型1.5 异步I/O模型 2 select函数3 select实战&#xff1a;实现多个套接字监听3.1 客户端3.2 服务端3.3 实验结果3.4 完整代码 在之前的网络编程中&#xff0c;我们遇到了一个问题&…

Qt TCP网络上位机的设计(通过网络编程与下位机结合)

目录 TCP 协议基础 QTcpServer 和 QAbstractSocket 主要接口函数 TCP 应用程序 1.服务端 2.客户端 上位机通过网络编程与下位机实现通信 TCP 协议基础 传输控制协议&#xff08;TCP&#xff0c;Transmission Control Protocol&#xff09;是一种面向连接的、可靠的、基于…

mysql从库设置为只读

直奔主题&#xff0c;mysql设置为只读后&#xff0c;无法增删改。 设置命令&#xff1a; mysql> set global read_only1; #1是只读&#xff0c;0是读写 mysql> show global variables like %read_only%; 以下是相关说明&#xff1a; 1、对于数据库读写状态&#xf…

详解RT-DETR网络结构/数据集获取/环境搭建/训练/推理/验证/导出/部署

论文地址&#xff1a;RT-DETR论文地址 代码地址&#xff1a;RT-DETR官方下载地址 目录 一、本文介绍 二、RT-DETR的网络结构 2.1、模型概览 2.2、高效混合编码器 2.3、IoU感知查询选择 2.4、 可扩展的RT-DETR 三、RT-DERT的环境搭建 四、免费数据集获取 五、获取RT-D…

爬楼梯(力扣LeetCode)动态规划

爬楼梯 题目描述 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢&#xff1f; 示例 1&#xff1a; 输入&#xff1a;n 2 输出&#xff1a;2 解释&#xff1a;有两种方法可以爬到楼顶。 1 阶 1 阶2 阶 示…

使用python 实现华为设备的SFTP文件传输

实验目的&#xff1a; 公司有一台CE12800的设备&#xff0c;管理地址位172.16.1.2&#xff0c;现在需要编写自动化脚本&#xff0c;通过SFTP实现简单的上传下载操作。 实验拓扑&#xff1a; 实验步骤&#xff1a; 步骤1&#xff1a;将本地电脑和ensp的设备进行桥接&#xff…

菜单的hover不同动画背景

CSS常用示例100专栏目录 本专栏记录的是经常使用的CSS示例与技巧&#xff0c;主要包含CSS布局&#xff0c;CSS特效&#xff0c;CSS花边信息三部分内容。其中CSS布局主要是列出一些常用的CSS布局信息点&#xff0c;CSS特效主要是一些动画示例&#xff0c;CSS花边是描述了一些CSS…

SWT/Jface(3): 表格中添加超链接

背景 实际业务中经常需要展示某个网站, 并且希望在展示的时候单击网站可直接访问, 本节演示在表格中如何添加超链接支持. 需求 假设我需要渲染一个Study类, 它只有三个属性id,name和website, 其中id只支持展示, name只支持编辑, 而website只支持单击时跳转到相应的网站, 效果…

Linux7设置ssh秘钥登录并关闭密码登录

说明&#xff1a;场景为windows使用WinScp远程登录linux服务 winscp安装教程&#xff1a;winscp安装及关联putty使用_putty.exe没有找到_cherishSpring的博客-CSDN博客 1.在window上生成公钥和秘钥&#xff0c;操作方式参考以下文章第3点&#xff1a; git关联云效使用教程_云…

Ps:使用钢笔工具绘制自由路径的技巧

只有熟练掌握使用钢笔工具绘制自由路径的技巧&#xff0c;才能快速完成复杂形状的创建以及精准抠图等工作。 钢笔工具是 Photoshop 中绘制路径的主要工具。无论是直线路径还是曲线路径&#xff0c;钢笔工具都能够提供高度的控制和精确度。 ◆ ◆ ◆ 绘制直线路径 绘制直线路径…

下载网页内容成HTML文件

今天遇到了一个非常好用的、开源的网页下载插件: SingleFile&#xff0c;它可以将当前网页里的文字、图片、超链接等&#xff0c;合并成单一的.html文件&#xff0c;便于保存和浏览查看。下面介绍SingleFile的安装和使用。 1、下载SingleFile插件 SingleFile官网地址&#xff…