【C语言】数据结构#实现堆

news2024/11/27 10:43:33


目录

(一)堆

(1)堆区与数据结构的堆

(二)头文件

(三)功能实现

 (1)堆的初始化

(2)堆的销毁

(3)插入数据

(4)删除堆顶的数据        

(5)得到堆顶的数据

(6)判断堆是否为空

(7)得到堆内数据个数


正文开始:

(一)堆

(1)堆区与数据结构的堆

          堆区和数据结构中的堆是两个不同的概念。

       

  1. 堆区 (Heap) :堆区是计算机内存中的一部分,用于存储动态分配的内存空间。在程序运行时,堆区用于存储使用 new 或 malloc 等方法分配的内存空间,在程序运行结束后,由程序员手动释放。堆区是一块较大的内存区域,用于存储动态分配的数据。堆区的大小可以动态增长或缩小,具有较高的灵活性。堆区的访问速度较慢,但能够存储较大的数据。

  2. 数据结构中的堆:在数据结构中,堆是一种特殊的树状结构,具有以下特点:

  • 堆是一个完全二叉树,即除了最底层外,其他层都是满的,最底层的结点从左到右连续排列。
  • 堆中的每个结点的值都大于等于(或小于等于)其子结点的值,根结点是树中最大(或最小)的结点。
  • 堆可以分为最大堆和最小堆,最大堆的根结点是整个堆中最大的元素,最小堆的根结点是整个堆中最小的元素。

        

         在数据结构中,堆通常用于实现优先队列(Priority Queue)和堆排序(Heap Sort)等算法。堆的插入和删除操作的时间复杂度都为 O(log n),其中 n 是堆中元素的个数。

(二)头文件

        STL(Standard Template Library)是C++标准库中的一个组件,提供了一系列的通用数据结构和算法,以及一些函数模板,用于简化C++程序的开发。STL包括了容器(Containers)、算法(Algorithms)和迭代器(Iterators)三个主要部分。

  1. 容器(Containers):STL提供了多种容器,包括向量(vector)、链表(list)、双端队列(deque)、集合(set)、映射(map)等。这些容器提供了不同的数据结构和操作,方便了数据的存储和处理。

  2. 算法(Algorithms):STL提供了一系列的算法,包括排序、查找、合并、变序、计数等等。这些算法可以对容器中的元素进行操作,使得程序更加高效和简洁。

  3. 迭代器(Iterators):STL的迭代器是一个泛型指针,用于遍历容器中的元素。迭代器提供了一种统一的访问容器元素的方式,使得算法可以独立于容器而使用。

        本文根据Cpp的STL来实现堆的功能,包括堆的初始化,销毁,插入数据,删除堆顶的数据,得到堆顶的数据,判断堆是否为空,得到堆内数据个数等七个功能接口。

        本文基于顺序表实现堆;

        这里不加解释的给出头文件,根据头文件实现堆的功能:

        命名:Heap.h

#pragma once

#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>

typedef int HPDatatype;

typedef struct Heap
{
	HPDatatype* a;//存储数据的数组
	int size;     //堆内数据的个数
	int capacity; //顺序表的容量
}HP;

//初始化
void HPinit(HP* php);

//销毁
void HPDestroy(HP* php);

//插入数据
void HPpush(HP* php, HPDatatype x);

//删除数据,规定删除堆顶的数据
void HPpop(HP* php);

//得到堆顶数据
HPDatatype HPtop(HP* php);

//判空
bool HPempty(HP* php);

//数据个数
int HPsize(HP* php);

         

(三)功能实现

 (1)堆的初始化

堆的初始化

        首先,函数接收的指针(被传入的地址)不为空(否则无法进行解引用操作),通过assert断言实现;

        将数组置空,顺序表的大小与容量置0;


//初始化
void HPinit(HP* php)
{
	assert(php);

	php->a = NULL;
	php->capacity = php->size = 0;
}

 

(2)堆的销毁

堆的销毁

          首先,函数接收的指针(被传入的地址)不为空(否则无法进行解引用操作),通过assert断言实现;

        释放掉动态申请的顺序表内的数组,顺序表的大小与容量置0;


//销毁
void HPDestroy(HP* php)
{
	assert(php);

	free(php->a);
	php->capacity = php->size = 0;

}

 

(3)插入数据

 

插入数据

         首先,函数接收的指针(被传入的地址)不为空(否则无法进行解引用操作),通过assert断言实现;

        其次判断数组内数据是否满了

        ——如果顺序表容量等于数组的大小,代表数据满了,那么进行扩容。Newcapacity的赋值通过三目操作符实现:如果capacity为初始值0,Newcapacity赋值为4,否则赋值为2*capacity。如果realloc申请失败,打印错误信息并返回。若申请成功,压入数据。

        ——如果数据没有满,直接在数组中插入数据,由于插入的数据不一定与原数据成堆,所以要进行向上调整

        调整需要交换,于是提前给出交换的功能接口:

 交换

//传址交换
void Swap(HPDatatype* p1, HPDatatype* p2)
{
	HPDatatype tem = *p1;
	*p1 = *p2;
	*p2 = tem;
}

 

 什么是向上调整?

         堆在逻辑上是二叉树,在物理上实际上是数组,数组的下标如下:

         在堆中,有一个规律:

  •         父节点下标 = (子节点下标 - 1) / 2;
  •         左子节点下标 = (父结点下标  * 2) + 1;
  •         右子节点下标 = (父结点下标  * 2) + 2;

        于是,我们可以通过一个节点的下标,找到他的父和子的下标 ;

本文以实现小堆为例 

向上调整

        将新插入的节点与其父节点比较,如果新节点小于父结点,两节点交换值,继续迭代进行;

         直到新节点的值大于等于父结点,或者已经比到了根节点才停止;


//push实现小堆的向上调整
void AdgustUP(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 HPpush(HP* php, HPDatatype x)
{
	assert(php);
	//数据满,realloc扩容,得到新的大容量顺序表
	if (php->capacity == php->size)
	{
		int Newcapacity = php->capacity == 0 ? 4 : php->capacity * 2;
		HPDatatype* tem = (HPDatatype*)realloc(php->a, Newcapacity * sizeof(HPDatatype));
		if (tem == NULL)
		{
			perror("realloc fail!");
			return;
		}
		php->a = tem;
		php->capacity = Newcapacity;
	}

	//数据不满,直接插入
	php->a[php->size] = x;
	php->size++;

	//向上调整
	AdgustUP(php->a,php->size-1);
}

 

(4)删除堆顶的数据        

删除数据

        删除数据规定的是删除堆顶的数据;

        函数接收的指针(被传入的地址)不为空(否则无法进行解引用操作),通过assert断言实现;

        如何删除?

        -直接删除,由于二叉树的兄弟节点是没有大小关系的,如果直接删除根节点,那么所有节点的下标减一,这意味着原来的的二叉树的结构就被完全破坏了,接下来只能重新建堆,代价太大。

        -先交换堆顶与最后一个数据,然后删除最后一个数据(其实就是原堆顶数据),然后进行向下调整;

        这样既没有完全破换二叉树的结构,只有一个数据需要调整位置,又操作简便只需size--即可。

向下调整

        思路与向上调整基本一致;


//小堆向下调整——找小
void AdgustDown(HPDatatype* a, int n, int parent)
{
	//假设左孩子小
	int child = parent * 2 + 1;
	while (child < n)
	{
		//如果右孩子小,假设不成立
		if (child + 1 < n && a[child] > a[child + 1])
		{
			child++;
		}
		//此时,child表示较小的孩子
		if (a[child] < a[parent])
		{
			Swap(&a[child], &a[parent]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}

	}

}

删除数据


//删除数据,规定删除堆顶的数据
void HPpop(HP* php)
{
	assert(php);
	//交换堆顶与最后一个数据
	Swap(&php->a[0], &php->a[php->size - 1]);
	//删除堆顶的数据
	php->size--;
	//向下调整
	AdgustDown(php->a, php->size,0);

}

(5)得到堆顶的数据

          首先,函数接收的指针(被传入的地址)不为空(否则无法进行解引用操作),通过assert断言实现;

        其次,堆不为空,通过assert断言实现;

        直接返回堆顶的数据即可;


//得到堆顶数据
HPDatatype HPtop(HP* php)
{
	assert(php);
	assert(!HPempty(php));

	return php->a[0];
}

 

(6)判断堆是否为空

         首先,函数接收的指针(被传入的地址)不为空(否则无法进行解引用操作),通过assert断言实现;

         直接返回判断表达式的值即可;(若为空,返回真(1);否则返回假(0))

//判空
bool HPempty(HP* php)
{
	assert(php);
	return php->size == 0;
}

 

(7)得到堆内数据个数

          首先,函数接收的指针(被传入的地址)不为空(否则无法进行解引用操作),通过assert断言实现;

        直接返回堆内数据个数即可;


//数据个数
int HPsize(HP* php)
{
	assert(php);

	return php->size;
}


完~

未经作者同意禁止转载 

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

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

相关文章

Vue3+Vite+TS+Pinia+ElementPlus+Router+Axios创建项目

目录 初始项目组成1. 创建项目1.1 下载项目依赖1.2 项目自动启动1.3 src 别名设置vite.config.ts配置文件tsconfig.json配置若新创项目ts提示1.4 运行测试2. 清除默认样式2.1 样式清除代码下载2.2 src下创建公共样式文件夹`style`2.3 main.js中引入样式2.4 安装`sass`解析插件2…

SpringCloud之Eureka注册中心和负载均衡

SpringCloud之Eureka注册中心和负载均衡 微服务技术栈认识微服务单体架构分布式架构微服务 微服务拆分及远程调用微服务拆分注意事项 Eureka注册中心提供者与消费者原理分析服务调用出现的问题Eureka的作用 使用流程1、搭建EurekaServer2、注册user-service3、在order-service完…

代码随想录算法训练营第三十一天 |基础知识,455.分发饼干,376.摆动序列,53.最大子序和(已补充)

基础知识&#xff1a; 题目分类大纲如下&#xff1a; #算法公开课 《代码随想录》算法视频公开课(opens new window)&#xff1a;贪心算法理论基础&#xff01;(opens new window),相信结合视频再看本篇题解&#xff0c;更有助于大家对本题的理解。 #什么是贪心 贪心的本质…

《区块链公链数据分析简易速速上手小册》第4章:交易数据分析(2024 最新版)

文章目录 4.1 解析交易输入和输出4.1.1 基础知识4.1.2 重点案例&#xff1a;追踪比特币交易4.1.3 拓展案例 1&#xff1a;以太坊交易的输入输出解析拓展案例1&#xff1a;以太坊交易的输入输出解析步骤1: 连接到以太坊网络步骤2: 获取交易数据步骤3: 解析交易输入结论 4.1.4 拓…

PyQt Python 使用 VTK ITK 进行分割 三维重建 医学图像可视化系统 流程

效果&#xff1a; 重建流程&#xff1a; 1. 输入 可以读取DICOM &#xff0c;nii nrrd 等数据 设置读取器以加载 DICOM 图像系列。 使用 itk::GDCMImageIO 作为 DICOM 图像的输入输出接口。 使用 itk::GDCMSeriesFileNames 获取指定路径下的所有 DICOM 文件名。 使…

Zabbix图形中文乱码问题(显示口口)解决办法

一 切换到zabbix安装目录assets/fonts下&#xff0c;下载字体 这里使用是nginxphp作为zabbix-web展示&#xff0c;使用find 命令查找 进入目录下&#xff0c;将原有字体备份&#xff0c;下载msyh字体 wget https://www.xxshell.com/download/sh/zabbix/ttf/msyh.ttf 二 修改配…

AI换脸(视频换脸)讲解-1

AI换脸是一种人工智能技术&#xff0c;它可以将一个人的面部表情和特征应用到另一个人的脸部上&#xff0c;以创建逼真的视频和图像。 首先&#xff0c;AI换脸技术需要大量的训练数据。这些数据通常是由多个人以不同的表情、姿态、光照条件下的照片或视频组成。通过使用人工智…

DolphinScheduler安装与配置

DolphinScheduler概述 Apache DolphinScheduler是一个分布式、易扩展的可视化DAG工作流任务调度平台。致力于解决数据处理流程中错综复杂的依赖关系&#xff0c;使调度系统在数据处理流程中开箱即用。 DolphinScheduler的主要角色如下&#xff1a; MasterServer采用分布式无…

Linux第46步_通过“添加自定义菜单”来学习menuconfig图形化配置原理

通过“添加自定义菜单”来学习menuconfig图形化配置原理&#xff0c;将来移植linux要用到。 自定义菜单要求如下: ①、在主界面中添加一个名为“My test menu”&#xff0c;此菜单内部有一个配置项。 ②、配置项为“MY TESTCONFIG”&#xff0c;此配置项处于菜单“My test m…

C# winfrom实例:四路激光测距雷达数据采集和波形图绘制

1.所述产品 产品型号&#xff1a;TFmini Plus 相关资料下载地址&#xff1a;http://www.benewake.com/download 产品名称&#xff1a;TFmini Plus激光雷达模组制造商公司&#xff1a;北醒&#xff08;北京&#xff09;光子科技有限公司 2.产品功能&#xff1a;TFmini Plus是基…

编辑器的新选择(基本不用配置)

Cline 不用看网上那些教程Cline几乎不用配置。 点击设置直接选择Chinese, C直接在选择就行了。 Cline是一个很好的编辑器&#xff0c;有很多懒人必备的功能。 Lightly 这是一个根本不用配置的C编辑器。 旁边有目录&#xff0c;而且配色也很好&#xff0c;语言标准可以自己…

vue 获取 form表格 的值 的方法

vue 获取 form表格 的值 代码 let discountLastMoney this.form.getFieldValue(discountLastMoney)-0

tee漏洞学习-翻译-3:TrustZone exploit for MSM8974

原文&#xff1a;http://bits-please.blogspot.com/2015/08/full-trustzone-exploit-for-msm8974.html 在这篇博文中&#xff0c;我们将介绍利用上一篇文章中描述的 TrustZone 漏洞的完整过程。 在开发此漏洞时&#xff0c;我只使用了我值得信赖的&#xff08;个人&#xff0…

Linux环境中的git

目录 1.要使用git&#xff0c;首先要安装git 2.首次使用git需要做的操作 3.git操作 1.要使用git&#xff0c;首先要安装git 指令&#xff1a;sudo yum install -y git 2.首次使用git需要做的操作 在gitee网页&#xff0c;在你的仓库中找到&#xff1a; 先将下面两行代码分别…

第12讲创建图文投票实现

创建图文投票实现 图文投票和文字投票基本一样&#xff0c;就是在投票选项里面&#xff0c;多了一个选项图片&#xff1b; <view class"option_item" v-for"(item,index) in options" :key"item.id"><view class"option_input&qu…

如何用 ChatGPT 做项目管理?

ChatGPT 可以通过创建和维护跨团队项目协作计划&#xff0c;让员工更容易理解他们的角色和职责。 这个协作计划里面会包括每个团队或个人要执行的具体任务&#xff0c;每个任务最后期限和任何事情之 间的依赖关系。 该场景对应的关键词库:(24 个) 项目管理、项目协作计划、跨…

蓝桥杯电子类单片机提升一——超声波测距

前言 单片机资源数据包_2023 一、超声波测距原理 二、超声波测距的应用 1.超声波的发射 2.单片机知识补充&#xff1a;定时器 3.超声波的接收与计时 4.距离的计算 1&#xff09;定时器1为16位自动重载&#xff0b;1T11.0592MHz 2&#xff09;定时器1为16位自动重载&am…

express 定时删除 oss 垃圾图片

一&#xff1a; 删除垃圾图片 思路&#xff1a; 获取 oss 中存储的所有图片文件&#xff1b;获取数据库中存储的图片文件数据&#xff1b;对比差异&#xff0c;不在数据库中的 oss 图片文件即为要删除的垃圾图片。 实现&#xff1a; 1、获取所有 oss 文件 import OSS from…

Stable Diffusion之最全详解图解

Stable Diffusion之最全详解图解 1. Stable Diffusion介绍1.1 研究背景1.2 学术名词 2.Stable Diffusion原理解析2.1 技术架构2.2 原理介绍扩散过程 3.1 Diffusion前向过程3.2 Diffusion逆向&#xff08;推断&#xff09;过程 1. Stable Diffusion介绍 Stable Diffusion是2022…

蓝桥杯第七届电子类单片机组程序设计

目录 前言 蓝桥杯大赛历届真题 一、第七届比赛题&#xff1a; 二、功能实现&#xff1a; 1.基础/模板部分 2.菜单模式的切换 3.数码管闪烁功能 4.led灯闪烁部分 5.对按键的处理 5.对ds1302的处理 三、代码实现 main.c onewire.c onewire.h ds1302.c ds1302.h 前言 …