详解(实现)堆的接口函数

文章目录

    • 堆的顺序存储
  • 准备工作
    • 创建头文件Heap.h
    • 创建源文件Heap.c
    • 头文件的包含
    • 定义保存堆数据的结构体
  • 初始化
  • 销毁堆
  • 插入数据
    • 向上调整算法
      • 图解
      • 算法代码
  • 删除堆顶
    • 向下调整算法
      • 图解
      • 代码
  • 取出堆顶数据
  • 求堆的数据个数
  • 判断堆是否为空
  • 全部代码
    • Heap.h
    • Heap.c

再了解堆之前我们先要了解树和二叉树的基本知识
可以看我的上一篇文章

  • 堆逻辑结构是完全二叉树,但堆一般用顺序表存储
  • 堆只有大堆(大顶堆)和小堆(小顶堆)
    大堆:左右孩子节点中存储的数据都必须小于等于父亲节点,根节点最大
    小堆:左右孩子节点中存储的数据都必须大于等于父亲节点,根节点最小

堆的顺序存储

如下图
请添加图片描述
通过下标就可以表现出二叉树的节点之间的关系
左孩子节点(leftchild)下标=父亲节点(parent)下标 *2+1

右孩子节点(rightchild)下标=父亲节点(parent)下标 *2+2

父亲节点(parent)下标=孩子节点(child-1)/2


准备工作

创建头文件Heap.h

将头文件和函数定义等放在Stack.h中,方便管理

创建源文件Heap.c

将接口函数的实现放在里面,方便管理

头文件的包含

#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>
  • stdio.h:用于标准输入输出等
  • assret.h:用于使用assret函数,实现报错
  • stdbool.h:用于使用布尔(bool)类型
  • stdlib.h:用于使用动态内存管理函数

定义保存堆数据的结构体

在这里插入图片描述
为什么要将队列里的数据的数据类型重命名?
这是为了以后如果改变了SL结构体中数据存储的类型时,
不用到处改函数参数等地方的数据类型,只要改typedef后的int 为对应要改成的数据类型就可以。

至于给结构体重命名则仅是为了方便使用


初始化

在这里插入图片描述


销毁堆

在这里插入图片描述


插入数据

堆的插入是插入在顺序表的末尾,然后在用向上调整算法使插入的数据到达正确位置

在这里插入图片描述


向上调整算法

向上调整算法:

要求已有的数据是堆

让孩子节点与它的父亲节点比较(假设是大堆)如果孩子节点大于父亲节点,就交换孩子节点和父亲节点,再让原父亲节点成为新的孩子节点
直到孩子节点不再大于父亲节点【因为已有的数据已经是堆】或者孩子节点已经是堆顶(child=0),这样插入的数据就到达了正确的位置,符合大堆的要求:左右孩子节点中存储的数据都必须大于等于父亲节点

图解

在这里插入图片描述
在这里插入图片描述
可以看见当向上调整算法结束后,新插入的节点已经在正确的位置,并且其他节点也满足大堆的条件

算法代码

在这里插入图片描述
交换函数
在这里插入图片描述


删除堆顶

在这里插入图片描述

向下调整算法

向上下调整算法:

要求根的左右子树都是堆

假设是大堆

左右孩子中更大的那一个与父亲节点的数据比较,如果大于父亲节点的数据就交换孩子节点和父亲节点的数据,再让原孩子节点成为新的父亲节点,循环上述过程直到左右孩子中更大的那一个比父亲节点小或者再产生的左孩子节点越界了(父亲节点已经是最后一层了)

图解

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

代码

在这里插入图片描述
交换函数
在这里插入图片描述


取出堆顶数据

在这里插入图片描述


求堆的数据个数

在这里插入图片描述


判断堆是否为空

堆为空就返回真,不为空就返回假

在这里插入图片描述


全部代码

Heap.h

#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>typedef int HPDataType;typedef struct Heap
{HPDataType* a;int size;int capacity;
}Heap;//初始化
void HeapInit(Heap* hp);
// 堆的销毁
void HeapDestory(Heap* hp);
// 堆的插入
void HeapPush(Heap* hp, HPDataType x);
// 堆的删除
void HeapPop(Heap* hp);
// 取堆顶的数据
HPDataType HeapTop(Heap* hp);
// 堆的数据个数
int HeapSize(Heap* hp);
// 堆的判空
bool HeapEmpty(Heap* hp);

Heap.c

#include"Heap.h"//初始化
void HeapInit(Heap* hp)
{assert(hp);//如果传入的hp为  空  就报错HPDataType* tmp = (HPDataType*)malloc(sizeof(HPDataType)*4);if (tmp == NULL){printf("HeapInit中mallo失败");exit(-1);//结束程序}hp->a = tmp;hp->capacity = 4;//设置容量为 4hp->size = 0;//size表示数据个数
}// 堆的销毁
void HeapDestory(Heap* hp)
{assert(hp);//如果传入的hp为  空  就报错free(hp->a);//释放a申请的空间hp->a = NULL;//把a置空,防止野指针hp->capacity = 0;hp->size = 0;
}//交换函数
void Swap(HPDataType* p, HPDataType* q)
{HPDataType tmp = *p;*p = *q;*q = tmp;
}//向上调整算法
void AdjustUP(HPDataType*a,int child)
{int parent = (child - 1) / 2;//通过下标关系找到插入的节点的父亲的下标while (child > 0)//当插入的节点为  堆顶 时结束循环{if (a[child] > a[parent])//如果孩子节点>父亲节点{Swap(&a[child],&a[parent]);//交换对应下标的数据child = parent;//让原来的父亲节点成为  新的  孩子节点parent = (child - 1) / 2;//通过下标关系找到新孩子节点的父亲节点的下标}else//如果孩子节点<=父亲节点{break;//结束循环}}
}// 堆的插入
void HeapPush(Heap* hp, HPDataType x)
{assert(hp);//如果传入的hp为  空  就报错if (hp->size == hp->capacity)//如果堆满了就增容{//增容HPDataType* tmp = (HPDataType*)realloc(hp->a, sizeof(HPDataType) * hp->capacity * 2);//在原容量的基础上增加一倍的容量if (tmp == NULL)//tmp为空表示  申请失败{printf("HeapPush中realloc失败");exit(-1);}hp->a = tmp;hp->capacity *= 2;//容量翻倍}hp->a[hp->size] = x;//将数据x插入顺序表末尾hp->size++;//增加数据个数//向上调整算法AdjustUP(hp->a,hp->size-1);//使用向上调整算法让插入的数据到达正确位置
}//向下调整算法
void AdjustDown(HPDataType* a, int parent,int n)
{int child = parent * 2 + 1;//通过下标关系找到左孩子节点的下标while (child < n)//如果孩子节点的下标越界就结束循环{if (child+1<n&&a[child + 1] > a[child])//右孩子下标不能越界,并且右孩子更符合条件{child++;//左孩子下标+1就是右孩子}if (a[child] > a[parent])//如果更符合条件的孩子节点>父亲节点{Swap(&a[child], &a[parent]);//交换对应下标的数据parent = child;//让原来的孩子节点 变成 新的父亲节点child = parent * 2 + 1;//产生新的左孩子下标}else//如果更符合条件的孩子节点<=父亲节点{break;//结束循环}}
}// 堆的删除
void HeapPop(Heap* hp)
{assert(hp);//如果传入的hp为  空  就报错assert(hp->size > 0);//删除数据时堆不能为空Swap(&hp->a[0],&hp->a[hp->size-1]);//交换堆顶和顺序表最后一个数据hp->size--;//size表示有效数据个数,size--就相当于顺序表最后一个数据删除//向下调整算法AdjustDown(hp->a,0,hp->size);//使用向下调整算法让交换到堆顶的数据到达正确位置//让交换后的堆依然满足堆的要求
}// 取堆顶的数据
HPDataType HeapTop(Heap* hp)
{assert(hp);//如果传入的hp为  空  就报错assert(hp->size > 0);//取数据时堆不能为空,如果为空就报错return hp->a[0];//堆顶数据就存储在顺序表下标为0的位置
}// 堆的数据个数
int HeapSize(Heap* hp)
{assert(hp);//如果传入的hp为  空  就报错return hp->size;//size表示有效数据个数
}// 堆的判空
bool HeapEmpty(Heap* hp)
{assert(hp);//如果传入的hp为  空  就报错return hp->size == 0;//如果size=0就表示堆为空
}

以上就是全部内容了,如果对你有帮助的话,可以点赞收藏支持一下!

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

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

相关文章

AI毕业论文降重GPTS,避免AI检测,高效完成论文

视频演示 AI毕业论文降重GPTS&#xff0c;避免AI检测&#xff0c;高效完成论文&#xff01; 开发目的 “毕业论文降重”GPTS应用&#xff0c;作用为&#xff1a;重新表述学术论文&#xff0c;降低相似性评分&#xff0c;避免AI检测。 使用地址 地址&#xff1a;毕业论文降重…

unraid docker.img扩容

unraid 弹Docker image disk utilization of 99%&#xff0c;容器下载/更新失败 我的版本是6.11.5&#xff0c;docker.img满了导致容器不能更新&#xff0c;遇到同样问题的可以先用docker命令清除一下仓库(当然不一定能清理出来&#xff0c;我已经清理过只清理出来1G多点&…

【四 (3)数据可视化之 Seaborn 常用图表及代码实现 】

目录 文章导航一、介绍二、安装Seaborn三、导入Seaborn四、设置可以中文显示五、占比类图表1、饼图2、环形图 六、比较排序类1、条形图2、箱线图3、小提琴图 七、趋势类图表1、折线图 八、频率分布类1、直方图 九、关系类图表1、散点图2、成对关系图3、热力图 文章导航 【一 简…

基于SpringBoot+Vue交流和分享平台的设计与实现(源码+部署说明+演示视频+源码介绍)

您好&#xff0c;我是码农飞哥&#xff08;wei158556&#xff09;&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。&#x1f4aa;&#x1f3fb; 1. Python基础专栏&#xff0c;基础知识一网打尽&#xff0c;9.9元买不了吃亏&#xff0c;买不了上当。 Python从入门到精通…

Apache zookeeper kafka 开启SASL安全认证

背景&#xff1a;我之前安装的kafka没有开启安全鉴权&#xff0c;在没有任何凭证的情况下都可以访问kafka。搜了一圈资料&#xff0c;发现有关于sasl、acl相关的&#xff0c;准备试试。 简介 Kafka是一个高吞吐量、分布式的发布-订阅消息系统。Kafka核心模块使用Scala语言开发…

【人工智能入门必看的最全Python编程实战(5)】

--------------------------------------------------------------------- 1.AIGC未来发展前景 未完持续… 1.1 人工智能相关科研重要性 拥有一篇人工智能科研论文及专利软著竞赛是保研考研留学深造以及找工作的关键门票&#xff01;&#xff01;&#xff01; 拥有一篇人工…

AIDD简介——分类和回归任务

&#x1f31e;欢迎来到AI生物医药的世界 &#x1f308;博客主页&#xff1a;卿云阁 &#x1f48c;欢迎关注&#x1f389;点赞&#x1f44d;收藏⭐️留言&#x1f4dd; &#x1f31f;本文由卿云阁原创&#xff01; &#x1f320;本阶段属于练气阶段&#xff0c;希望各位仙友顺利…

《ARM汇编与逆向工程 蓝狐卷 基础知识》

大家好&#xff0c;我是爱编程的喵喵。双985硕士毕业&#xff0c;现担任全栈工程师一职&#xff0c;热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。…

Ubuntu20下C/C++编程开启TCP KeepAlive

1、在linux下&#xff0c;测试tcp保活&#xff0c;可以使用tcp自带keepalive功能。 2、几个重要参数&#xff1a; tcp_keepalive_time&#xff1a;对端在指定时间内没有数据传输&#xff0c;则向对端发送一个keepalive packet&#xff0c;单位&#xff1a;秒 tcp_keep…

拌合楼内部管理系统开发(一)立个flag,开始做准备

前言&#xff1a;项目背景情况介绍 公司有意开发一套适合拌合楼的内部管理系统给到客户使用&#xff0c;接触过一家拌合楼行业内号称标杆的企业&#xff0c;去过参观学习的都觉得他们软件好用&#xff0c;但是从软件开发角度看&#xff0c;就是crud钉钉机器人无人值守。虽然公司…

Python语法糖

N u m P y NumPy NumPy的 n d i t e r nditer nditer nditer 是 NumPy 提供的一种多维迭代器&#xff0c;用于对多维数组进行迭代操作。它可以替代传统的嵌套循环&#xff0c;在处理多维数组时更加方便和高效。 迭代器可以按照不同的顺序遍历数组的元素&#xff0c;也可以控制…

JDK8和JDK11在Ubuntu18上切换(解决nvvp启动报错)

本文主要介绍JDK8和JDK11在Ubuntu18上切换&#xff0c;以供读者能够理解该技术的定义、原理、应用。 &#x1f3ac;个人简介&#xff1a;一个全栈工程师的升级之路&#xff01; &#x1f4cb;个人专栏&#xff1a;计算机杂记 &#x1f380;CSDN主页 发狂的小花 &#x1f304;人…

C++的类和对象(七):友元、内部类

目录 友元 友元函数 友元类 内部类 匿名对象 拷贝对象时的一些编译器优化 再次理解类和对象 友元 基本概念&#xff1a;友元提供了一种突破封装的方式&#xff0c;有时提供了便利&#xff0c;但是友元会增加耦合度&#xff0c;破坏了封装&#xff0c;所以友元不宜多用&…

[嵌入式系统-39]:龙芯1B 开发学习套件 -10-PMON启动过程Sstart.S详解

目录 一、龙芯向量表与启动程序的入口&#xff08;复位向量&#xff09; 1.1 复位向量&#xff1a; 1.2 代码执行流程 1.3 计算机的南桥 VS 北桥 二、PMON代码执行流程 三、Start.S详解 3.1 CPU初始化时所需要的宏定义 &#xff08;1&#xff09;与CPU相关的一些宏定义…

北斗卫星在桥隧坡安全监测领域的应用及前景展望

北斗卫星在桥隧坡安全监测领域的应用及前景展望 北斗卫星系统是中国独立研发的卫星导航定位系统&#xff0c;具有全球覆盖、高精度定位和海量数据传输等优势。随着卫星导航技术的快速发展&#xff0c;北斗卫星在桥隧坡安全监测领域正发挥着重要的作用&#xff0c;并为相关领域…

element-plus 完成下拉切换功能

项目场景&#xff1a; element-plus element-plus 完成下拉切换功能&#xff0c;选用了popover 组件去进行样式修改&#xff0c;本来大概是要实现下面这样的样式效果&#xff0c;没想到调整的时候&#xff0c;这个选择的高亮模块总是超出。 实现效果&#xff1a; 解决方案&am…

android HAL层崩溃排查记录

要最近在调试系统HDMI CEC功能时&#xff0c;遇到一个奇怪的崩溃问题&#xff0c;这边记录下。 初步分析 先上日志&#xff1a; --------- beginning of crash 03-06 10:48:25.503 1133 1133 F DEBUG : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** **…

微信小程序 - 基于scroll view 实现下拉刷新

简介 本文会基于scroll view 实现下拉刷新效果&#xff0c;在下拉的时候会进入loading状态。 实现效果 效果如上图所示&#xff0c;在下拉到底部时候&#xff0c;会出现loading条&#xff0c;在处理完成后loading条消失。 具体代码 布局 <scroll-view scroll-y style&qu…

【AIGC调研系列】通义灵码与copilot的对比

通义灵码与GitHub Copilot的对比主要集中在几个方面&#xff1a;代码编写能力、免费性、操作界面和适配性。 首先&#xff0c;在代码编写能力上&#xff0c;虽然GitHub Copilot在整体上要强于通义灵码&#xff0c;但通义灵码的能力也不算弱&#xff0c;并且在某些特定的小类任…