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

文章目录

    • 堆的顺序存储
  • 准备工作
    • 创建头文件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://xiahunao.cn/news/2868315.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

Unity AI Navigation插件快速使用方法

AI Navigation插件使您能够创建能够在游戏世界中智能移动的角色。这些角色利用的是根据场景几何结构自动生成的导航网格。障碍物可以让您在运行时改变角色的导航路径。 演示使用的Unity版本为Tuanjie 1.0.0,团结引擎是Unity中国的引擎研发团队基于Unity 2022 LTS版本为中国开发…

【算法杂货铺】模拟

目录 &#x1f308;前言&#x1f308; &#x1f4c1;1576. 替换所有的问号​编辑 &#x1f4c1; 495. 提莫攻击 &#x1f4c1; 6. Z 字形变换 &#x1f4c1;38. 外观数列 &#x1f4c1;1419. 数青蛙 &#x1f4c1; 总结 &#x1f308;前言&#x1f308; 欢迎观看本期【算…

SkyWalking上报Java应用数据

重要 本文中含有需要您注意的重要提示信息&#xff0c;忽略该信息可能对您的业务造成影响&#xff0c;请务必仔细阅读。 通过SkyWalking为应用埋点并上报链路数据至可观测链路 OpenTelemetry 版后&#xff0c;可观测链路 OpenTelemetry 版即可开始监控应用&#xff0c;您可以…

本地文件包含漏洞利用

目录 前期信息收集获取网站权限获取服务器权限纵向提权 前期信息收集 拿到目标的资产&#xff0c;先试一下IP能不能访问 探测一下目标的端口运行的是什么服务 nmap -sC -sV xx.xx9.95.185 -Pn获取网站权限 我们可以知道目标的80端口上运行着http服务&#xff0c;服务器是u…

【每日力扣】40.组合总和II与701. 二叉搜索树中的插入操作

&#x1f525; 个人主页: 黑洞晓威 &#x1f600;你不必等到非常厉害&#xff0c;才敢开始&#xff0c;你需要开始&#xff0c;才会变的非常厉害。 40.组合总和II 给定一个候选人编号的集合 candidates 和一个目标数 target &#xff0c;找出 candidates 中所有可以使数字和为…

【研发日记】Matlab/Simulink技能解锁(二)——在Matlab Function编辑窗口Debug

文章目录 前言 行断点 条件断点 按行步进 Watch Value 分析和应用 总结 前言 见《【研发日记】Matlab/Simulink技能解锁(一)——在Simulink编辑窗口Debug》 行断点 当Matlab Function出现异常时&#xff0c;如果能确定大致的代码段&#xff0c;就可以在相应的行上设置一…

综合知识篇00-综合知识考点汇总目录(2024年软考高级系统架构设计师冲刺知识点总结-综合知识篇-先导篇)

专栏系列文章推荐&#xff1a; 2024高级系统架构设计师备考资料&#xff08;高频考点&真题&经验&#xff09;https://blog.csdn.net/seeker1994/category_12593400.html 【历年案例分析真题考点汇总】与【专栏文章案例分析高频考点目录】&#xff08;2024年软考高级…

解析编程中不可或缺的基础:深入了解结构体类型

精琢博客&#xff0c;希望可以给大家带来收获~ 博主主页&#xff1a;17_Kevin-CSDN博客 收录专栏&#xff1a;《C语言》 引言 在编程中&#xff0c;结构体是一种自定义的数据类型&#xff0c;它允许开发人员将不同类型的数据组合在一起&#xff0c;并为其定义相关属性和行为。…

(四)Android布局类型(线性布局LinearLayout)

线性布局&#xff08;LinearLayout&#xff09;&#xff1a;按照一定的方向排列组件&#xff0c;方向主要分为水平方向和垂直方向。方向的设置通过属性android:orientation设置 android:orientation 其取值有两种 水平方向&#xff1a;android:orientation"horizontal&…

RPC通信原理(一)

RPC通信原理 RPC的概念 如果现在我有一个电商项目&#xff0c;用户要查询订单&#xff0c;自然而然是通过Service接口来调用订单的实现类。 我们把用户模块和订单模块都放在一起&#xff0c;打包成一个war包&#xff0c;然后再tomcat上运行&#xff0c;tomcat占有一个进程&am…

【NestJS 编程艺术】3. 探索NestJS的高效开发:nest-cli的全面指南

在现代的 Node.js 服务端开发中&#xff0c;NestJS 以其优雅的架构和强大的功能集成为了开发者的首选框架之一。而这一切的起点&#xff0c;都始于nestjs/cli这个强大的命令行工具。本文将深入探讨nest-cli的核心功能&#xff0c;帮助开发者高效地创建、构建和管理 NestJS 项目…

UDP通讯测试

参考资料&#xff1a;UNIX网络编程 实验平台&#xff1a;PC为client&#xff0c;RaspberryPi为server 基本类型和接口函数&#xff0c;参考man手册 #include <sys/socket.h>struct sockaddr {sa_family_t sa_family; /* Address family */char sa_…

【三】【单片机】有关数码管的实验

静态数码管 段选 首先看74HC138译码器&#xff0c;我们通过控制P22,P23,P24来控制选择LED1,LED2,LED3...... P24,P23,P22三个不同的二进制数&#xff0c;组成一个十进制数。P24对应二进制的最高位&#xff0c;P23对应二进制的中间位&#xff0c;P22对应二进制的最低位。利用P…

CSS 超出部分显示省略号,一个合格的初级前端工程师需要掌握的模块笔记

单行超出显示省略号 多行超出显示省略号 单行超出显示省略号 直接看代码&#xff1a; desktop demo 你问我为何时常沉默&#xff0c;有的人无话可说&#xff0c;有的话无人可说.你问我为何时常沉默&#xff0c;有的人无话可说&#xff0c;有的话无人可说. 效果图&#xff…

除了「au revoir」,「再见」还能怎么说?柯桥成人学外语来银泰附近

1. Je dois y alle#15857575376r I have to go there Y there&#xff0c;意思是“我要走了”。 例如&#xff0c;”Moi, je dois y aller.” 对不起&#xff0c;我该走了。 如果你和同伴都要离开&#xff0c;那就可以说"On y va"&#xff0c;它相当于英语里…

体系班第十六节(图论)

邻接矩阵法 1图的数据结构抽象 #include<vector> #include<unordered_map> #include<unordered_set> using namespace std; //点结构的描述&#xff0c;由值入度出度后继节点和边构成 class node { public:int value;int in;int out;vector<node*> n…

详解VXLAN

海翎光电的小编今天为大家介绍了什么是VXLAN&#xff0c;以及VXLAN的基本概念和工作原理。 什么是VXLAN VXLAN&#xff08;Virtual eXtensible Local Area Network&#xff0c;虚拟扩展局域网&#xff09;&#xff0c;是由IETF定义的NVO3&#xff08;Network Virtualization ov…

快速了解JavaScript

1.1 javaScript 历史 创始人 布兰登 艾奇 生于1961年 在1995设计LiveScript后改名为JavaScript 1.2 javaScript 是什么类型的语言 JavaScript是一种在客户端运行的脚本语言&#xff08;不需要编译&#xff0c;由js引擎逐行解释执行&#xff09; 1.3 JavaScript可以做什么 …

libevent中的链接监听器

链接监听器-evconnlistener 链接监听器封装了socket通信相关函数&#xff0c;比如socket,bind,listen,accept这几个函数。此时等待新的客户端到来&#xff0c;如果有新的客户端连接&#xff0c;那么内部先调用accept处理&#xff0c;然后调用用户指定的回调函数。 typedef vo…

HMAC算法:数据传输的保护神

title: HMAC算法&#xff1a;数据传输的保护神 date: 2024/3/16 16:50:53 updated: 2024/3/16 16:50:53 tags: HMAC算法消息认证哈希函数密钥管理数据安全网络通信防篡改 HMAC算法起源&#xff1a; HMAC&#xff08;Hash-based Message Authentication Code&#xff09;算法是…