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

文章目录

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

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

相关文章

云备份项目2

云备份项目 文章目录 云备份项目4. 服务端代码设计4.1 服务端工具类实现4.1.1 文件实用工具类设计4.1.2 Json实用工具类设计 4.2 服务端配置信息模块实现4.2.1 系统配置信息4.2.2 单例文件配置类设计 4.3 服务端数据管理模块实现4.3.1 备份数据类的实现4.3.2 数据管理类的设计 …

[BJDCTF2020]Cookie is so stable

hint提示查看cookies flag.php页面我们先随便输入一个名字 输入后我们重新进一次flag.php&#xff0c;发现cookie里存储了刚刚登陆时输入的用户名&#xff0c;直接猜是ssti 尝试后根据ssti特征判断是twig模板 {{_self.env.registerUndefinedFilterCallback("exec")…

论文阅读——RemoteCLIP

RemoteCLIP: A Vision Language Foundation Model for Remote Sensing 摘要——通用基础模型在人工智能领域变得越来越重要。虽然自监督学习&#xff08;SSL&#xff09;和掩蔽图像建模&#xff08;MIM&#xff09;在构建此类遥感基础模型方面取得了有希望的结果&#xff0c;但…

AI智慧校园电子班牌云平台源码

目录 家长端 学校端 电子围栏 亲情通话 课堂答题 移动化管理模式 统一资源管理平台 模板内容智能更换 家校互联 家长端 多场景通话:上学放学联系、紧急遇险求助联系、日常亲情通话关注孩子人身安全:到校离校情况、进入危险区域预警等。 学校端 课堂秩序管理:提高教…

鸿蒙Harmony应用开发—ArkTS声明式开发(容器组件:Counter)

计数器组件&#xff0c;提供相应的增加或者减少的计数操作。 说明&#xff1a; 该组件从API Version 7开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 子组件 可以包含子组件。 接口 Counter() 从API version 9开始&#xff0c;该接口…

【网站项目】320社区物业管理系统

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

MySQL-HMA 高可用故障切换

本章内容&#xff1a; 了解MySQL MHA搭建MySQL MHAMySQL MHA故障切换 1.案例分析 1.1.1案例概述 目前 MySQL 已经成为市场上主流数据库之一&#xff0c;考虑到业务的重要性&#xff0c;MySQL 数据库 单点问题已成为企业网站架构中最大的隐患。随着技术的发展&#xff0c;MHA…

广度优先算法(一篇文章讲透)

目录 引言 一、算法概述 二、算法步骤 1 初始化 2 循环处理 三、算法应用 1 图的最短路径问题 2 网络爬虫 3 社交网络分析 4 游戏路径搜索 事例 四、算法特点与性能 五、性能优化 1 剪枝策略&#xff1a; 2 使用高效的数据结构&#xff1a; 3 并行化处理&#…

sparksession对象简介

什么是sparksession对象 spark2.0之后&#xff0c;sparksession对象是spark编码的统一入口对象&#xff0c;通常我们在rdd编程时&#xff0c;需要SparkContext对象作为RDD编程入口&#xff0c;但sparksession对象既可以作为RDD编程对象入口&#xff0c;在sparkcore编程中可以通…

这些赚钱项目可以主业副业两不误

在如今竞争激烈的社会中&#xff0c;拥有一份可靠的职业是我们追求稳定收入的首选。然而&#xff0c;为了应对生活成本的不断增加和个人发展的需求&#xff0c;更多的人开始寻求一种既能兼顾主业&#xff0c;又能增加额外收入的副业机会。 生活中有这么一些人&#xff0c;他们将…

YOLOv7 | 添加GSConv,VoVGSCSP等多种卷积,有效提升目标检测效果,代码改进(超详细)

⭐欢迎大家订阅我的专栏一起学习⭐ &#x1f680;&#x1f680;&#x1f680;订阅专栏&#xff0c;更新及时查看不迷路&#x1f680;&#x1f680;&#x1f680; YOLOv5涨点专栏&#xff1a;http://t.csdnimg.cn/QdCj6 YOLOv7专栏&#xff1a; http://t.csdnimg.cn/dy…

代码随想录训练营Day24:● 理论基础 ● 77. 组合

理论基础 回溯算法解决的问题 回溯法&#xff0c;一般可以解决如下几种问题&#xff1a; 组合问题&#xff1a;N个数里面按一定规则找出k个数的集合 切割问题&#xff1a;一个字符串按一定规则有几种切割方式 子集问题&#xff1a;一个N个数的集合里有多少符合条件的子集 排列…