堆和二叉树的动态实现(C语言实现)

news2024/11/15 10:49:14

请添加图片描述

✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅
✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨
🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿
🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟
🌟🌟 追风赶月莫停留 🌟🌟
🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀
🌟🌟 平芜尽处是春山🌟🌟
🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟
🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿
✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨
✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅

🍋堆和队二叉树

  • 🍑二叉树
    • 🍍二叉树的含义
    • 🍍二叉树的结构
    • 🍍二叉树的存储结构
  • 🍑堆
    • 🍍堆的含义
    • 🍍堆的结构
    • 🍍堆的实现
      • 🍌补充条件
      • 🍌堆的初始化
      • 🍌堆的销毁
      • 🍌堆的插入
      • 🍌 堆的删除
      • 🍌取堆顶的数据
      • 🍌堆的数据个数
      • 🍌堆的判空
      • 🍌堆的整体代码实现

🍑二叉树

🍍二叉树的含义

二叉树是一种树形结构,其特点是每个节点最多有两个子树。

二叉树是一种有序树,这意味着它的子树按照一定的顺序排列,通常左子树出现在右子树之前。二叉树的递归定义可以描述为:二叉树可以是空的,也可以由一个根节点和两个互不相交的子树组成,这两个子树分别称为左子树和右子树。左子树和右子树自身也构成二叉树。

🍍二叉树的结构

在这里插入图片描述

在这里插入图片描述
现实中的二叉树:
在这里插入图片描述

在这里插入图片描述

现实中的树,就是我们学过的二叉树倒过来的样子,大家可以把手机屏幕倒过来看试试。

🍍二叉树的存储结构

二叉树分为顺序存储和链式存储

在这里插入图片描述

顺序存储:类似于数组的存储形式,但只有完全二叉树才会用顺序存储,这样才不会造成空间的浪费

在这里插入图片描述

链式存储:利用了链表的性质。每个节点都存储了上个树和下个树的位置,这也就是带头指针的双链表结构

🍑堆

🍍堆的含义

堆是计算机科学中一类特殊的数据结构的统称。堆通常是一个可以被看做一棵树的数组对象。堆总是满足下列性质:
(1)堆中某个结点的值总是不大于或不小于其父结点的值;
(2)堆总是一棵完全二叉树。
(3)将根结点最大的堆叫做最大堆或大根堆,根结点最小的堆叫做最小堆或小根堆。常见的堆有 二叉堆、斐波那契堆等。
(4)堆的物理结构本质上是顺序存储的,是线性的。但在逻辑上不是线性的,是完全二叉树的这种逻辑储存结构。 堆的这个数据结构,里面的成员包括一维数组,数组的容量,数组元素的个数,有两个直接后继。

🍍堆的结构

在这里插入图片描述

堆的结构就是特殊的二叉树结构,也就是上图中完全二叉树的样子

🍍堆的实现

在这里插入图片描述

堆的实现又分为大堆和小堆
大堆:任何父节点都大于等于子节点。
小堆:任何父节点都小于等于子节点。
两个子节点之间的大小没有明确规定

🍌补充条件

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

typedef int HPDatetype;
typedef struct Heap
{
	HPDatetype* a;
	int catacity;
	int size;
}HP;

void Swap(HPDatetype *a1, HPDatetype *a2)
{
	HPDatetype cur = *a1;
	*a1 = *a2;
	*a2 = cur;
}

Swap()函数是交换两个数的作用,是利用结构体形式创建的堆

🍌堆的初始化

void HeapInia(HP* ps)
{
	assert(ps);//防止堆为空
	ps->a = NULL;
	ps->size = ps->catacity = 0;
}

🍌堆的销毁

void HeapDestroy(HP* ps)
{
	assert(ps);//防止堆为空
	free(ps->a);
	ps->a = NULL;
	ps->size = 0;
	ps->catacity = 0;
}

🍌堆的插入

void AdjustUp(HPDatetype* a, int child)
{
	int parent = (child - 1) / 2;
	while (child > 0)
	{
		if (a[child] < a[parent])
		{
			Swap(&a[child], &a[parent]);
			child = parent;
			parent = (parent - 1) / 2;
		}
		else
		{
			break;
		}
	}
}

void HeapPush(HP* ps, HPDatetype x)
{
	assert(ps);//防止堆为空
	if (ps->catacity == ps->size)
	{
		if (ps->catacity == 0)
		{
			ps->catacity = 2;
		}
		else
		{
			ps->catacity *= 2;
		}
		int newcatacity = ps->catacity;

		HPDatetype* cur = (HPDatetype*)realloc(ps->a, sizeof(HPDatetype) * newcatacity);
		if (cur == NULL)
		{
			perror("realloc fail");
			exit(-1);
		}
		ps->a = cur;
		ps->catacity = newcatacity;
	}
	ps->a[ps->size] = x;
	(ps->size)++;

	AdjustUp(ps->a, ps->size - 1);
}

AdjustUp()函数是把子节点向上调整的作用,因为我们利用数组形式建立堆,只能分为大堆和小堆,所以需要重新设计一个函数来调整子节点的位置。在这里我们是创建小堆。关于怎么向上找父节点,是利用了数组的位置特性。数组是从0开始,大家就可以找规律,以父节点找子节点就是需要加1再除以2,以子节点找父节点就是减1除以2。

🍌 堆的删除

void AdjustLown(HPDatetype* a, int n, int parent)//向下调整
{
	int child = parent * 2 + 1;
	while (child < n)
	{
		if (child + 1 < n && a[child] > a[child + 1])
		{
			child++;
		}

		if (a[child] < a[parent])
		{
			Swap(&a[child], &a[parent]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}
	}
}

void HeapPop(HP* ps)
{
	assert(ps);
	assert(ps->size > 0);

	Swap(&(ps->a[0]), &(ps->a[ps->size - 1]));
	(ps->size)--;

	AdjustLown(ps->a, ps->size, 0);//向下调整

}

堆的删除,在这里我们是删除的堆顶数据。
首先我们是先把堆顶数据和堆尾数据交换,然后再删除堆顶数据,最后利用函数AdjustLown()进行向下调整就行。
如果是小堆,取出来的数据就是依次变大,相反是大堆,取出来的数据就是依次变小。
堆在这里还有一个应用,就是堆排序。小堆就是升序,大堆就是降序。

🍌取堆顶的数据

HPDatetype HeapTop(HP* ps)
{
	assert(ps);
	assert(ps->size > 0);

	return ps->a[0];
}

返回堆顶数据即可

🍌堆的数据个数

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

直接返回ps->size即可

🍌堆的判空

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

注意,这里判空用到bool需要头文件名#include<stdbool.h>

🍌堆的整体代码实现

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

typedef int HPDatetype;
typedef struct Heap
{
	HPDatetype* a;
	int catacity;
	int size;
}HP;

void HeapInia(HP* ps)
{
	assert(ps);
	ps->a = NULL;
	ps->catacity = ps->size = 0;
}

void HeapDestroy(HP* ps)
{
	assert(ps);
	free(ps->a);
	ps->a = NULL;
	ps->size = ps->catacity;
}

void Swap(HPDatetype* a1, HPDatetype* a2)
{
	HPDatetype cur = *a1;
	*a1 = *a2;
	*a2 = cur;
}

void AdjustUp(HPDatetype* a, int child)
{
	int parent = (child - 1) / 2;
	while (child > 0)
	{
		if (a[child] < a[parent])
		{
			Swap(&a[child], &a[parent]);
			child = parent;
			parent = (parent - 1) / 2;
		}
		else
		{
			break;
		}
	}
}

void HeapPush(HP* ps, HPDatetype x)
{
	assert(ps);
	if (ps->size == ps->catacity)
	{
		if (ps->catacity == 0)
			ps->catacity = 2;
		else
			ps->catacity *= 2;
		int newcatacity = ps->catacity;
		HPDatetype* cur = (HPDatetype*)realloc(ps->a, sizeof(HPDatetype) * newcatacity);
		if (cur == NULL)
		{
			perror("realloc fail");
			exit(-1);
		}
		ps->a = cur;
		ps->catacity = newcatacity;
	}
	ps->a[ps->size] = x;
	(ps->size)++;

	AdjustUp(ps->a, ps->size - 1);

}

void AdjustLown(HPDatetype* a, int n, int parent)
{
	int child = parent * 2 + 1;
	while (child < n)
	{
		if (child + 1 < n && a[child] > a[child + 1])
		{
			child++;
		}

		if (a[child] < a[parent])
		{
			Swap(&a[child], &a[parent]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}
	}
}

void HeapPop(HP* ps)
{
	assert(ps);
	assert(ps->size > 0);

	Swap(&(ps->a[0]), &(ps->a[ps->size - 1]));
	(ps->size)--;

	AdjustLown(ps->a, ps->size, 0);

}

HPDatetype HeapTop(HP* ps)
{
	assert(ps);
	assert(ps->size > 0);

	return ps->a[0];
}

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

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

void HeapPrint(HP *ps)
{
	for (int i = 0; i < ps->size; i++)
	{
		printf("%d ", ps->a[i]);
	}
	printf("\n");
}

int main()
{
	int a[] = { 65,100,70,32,50,60 };
	int size = sizeof(a) / sizeof(a[0]);
	HP ps;
	HeapInia(&ps);
	for (int i = 0; i < size; i++)
	{
		HeapPush(&ps, a[i]);
	}
	HeapPrint(&ps);

	int net = HeapSize(&ps);

	//堆排序
	while (!HeapEmpty(&ps))
	{
		printf("%d ", HeapTop(&ps));
		HeapPop(&ps);
	}
	
	printf("%d ", net);

	HeapDestroy(&ps);

	return 0;
}

上面我也不充了堆排序,大家有兴趣可以试试,由于我这里是建的小堆,所以排出来的序是升序。

有不足的地方欢迎大家指正,谢谢!!!

请添加图片描述

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

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

相关文章

【pyinstaller打包记录】Windows系统打包exe后,onnxruntime报警告(Init provider bridge failed)

简介 PyInstaller 是一个用于将 Python 程序打包成可执行文件&#xff08;可执行程序&#xff09;的工具。它能够将 Python 代码和其相关的依赖项&#xff08;包括 Python 解释器、依赖的模块、库文件等&#xff09;打包成一个独立的可执行文件&#xff0c;方便在不同环境中运行…

从零学习Linux操作系统 第三十部分 部署Anisble

一、ansible实验环境的部署 主控机 更改服务器主机名 hostnamectl set-hostname westos_ansible.westos.org 主服务器需要能够实现上网 修改网卡使之能够上网 能ping通 代表可以连接外网 搭载本地软件仓库 并且挂载镜像 装载 dnf install httpd -y 让其开机启动并且…

MySQL王国:从基础到高级的完整指南【文末送书-28】

文章目录 MySQL从入门到精通第一部分&#xff1a;MySQL基础第二部分&#xff1a;MySQL进阶第三部分&#xff1a;MySQL高级应用 MySQL从入门到精通&#xff08;第3版&#xff09;&#xff08;软件开发视频大讲堂&#xff09;【文末送书-28】 MySQL从入门到精通 MySQL是一种开源…

WiFi模块赋能智能手表:拓展功能与提升连接性

随着科技的不断进步&#xff0c;智能手表正逐渐成为现代人生活中不可或缺的智能配饰。其中&#xff0c;WiFi模块的应用为智能手表带来了更多强大的功能和更高的连接性&#xff0c;为用户提供了更为便捷、智能化的使用体验。本文将深入探讨WiFi模块在智能手表中的应用。 远程通信…

vue实现xml,sql,JSON自动格式化高亮

实现xml&#xff0c;json&#xff0c;sql代码组件格式化高亮&#xff1a; 需要下载的依赖&#xff1a; <template><div class"box"><div class"top" v-if"flag"><span class"text">Theme:</span><…

微擎安装,卡在“安装微擎”界面

进入install.php&#xff0c;点击【在线安装】 下一步配置数据库&#xff0c;开始安装系统 然后显示进度条&#xff0c;进度条一闪而过 然后就没有进度条显示了&#xff0c;一直卡在这里 第一次等了好久&#xff0c; 删除目录下的文件&#xff0c;重装还是这样 再重启服务器&…

嵌入式蓝桥杯做题总结

第十二届省赛 按键代码 ——自认为比较巧妙&#xff0c;定时器3被设置为10ms进入一次中断&#xff0c;代替了HAL_Delay(10)的方法消抖&#xff1b; 运用状态机机思想实现检测多个按键检测——且分为两个状态&#xff0c;其中一个状态PB&#xff11;和PB&#xff12;的按键不…

Claude 3 模型列表

claude-3-opus-20240229 这个模型就好

解锁AI大模型秘籍:未来科技的前沿探索

在当今这个技术高速发展的时代&#xff0c;人工智能&#xff08;AI&#xff09;已经成为了我们生活中不可或缺的一部分。从简单的个人助手到复杂的数据分析和决策制定&#xff0c;AI的应用范围日益扩大&#xff0c;其目的是为了让我们的生活变得更加智能化。本文旨在探讨AI如何…

计网面试题整理下

1. HTTP常见的状态码有哪些&#xff1f; 常见状态码&#xff1a; 200&#xff1a;服务器已成功处理了请求。 通常&#xff0c;这表示服务器提供了请求的网页。301 &#xff1a; (永久移动) 请求的网页已永久移动到新位置。 服务器返回此响应(对 GET 或 HEAD 请求的响应)时&am…

STM32CubeMX学习笔记10 ---低功耗模式

在实际使用中很多产品都需要考虑低功耗的问题&#xff0c;STM32F10X提供了三种低功耗模式&#xff1a;睡眠模式&#xff08;Sleep mode&#xff09;、停机模式&#xff08;Stop mode&#xff09;和待机模式&#xff08;Standby mode&#xff09;。这些低功耗模式可以有效减少系…

gRPC-第二代rpc服务

在如今云原生技术的大环境下&#xff0c;rpc服务作为最重要的互联网技术&#xff0c;蓬勃发展&#xff0c;诞生了许多知名基于rpc协议的框架&#xff0c;其中就有本文的主角gRPC技术。 一款高性能、开源的通用rpc框架 作者作为一名在JD实习的Cpper&#xff0c;经过一段时间的学…

使用postman测试若依登录接口API-2

请求方式 由于登录控制器可知&#xff1a;该请求方式为Post请求 请求地址 在请求路径栏输入请求地址&#xff0c;如下图所示&#xff1a; 参数体 在Body键入所需参数&#xff0c;类型选择raw,数据格式选择"JSON"&#xff1a;如下图所示&#xff1a; 认证成功与失败…

SpringBoot-Thymeleaf

1.概念 Thymeleaf是一个模板引擎&#xff0c;它可以在我们开发前后端混合应用时发挥动态的从后端获取数据&#xff0c;并且展示在前端页面&#xff0c;它的出现代替了JSP 2.入门程序 分析Thymeleaf的源码可知&#xff0c;他的默认路径是templates&#xff0c;并且文件的后缀必须…

低代码平台开发实践:基于React的高效构建与创新【文末送书-29】

文章目录 背景低代码平台简介基于React的优势低代码平台的实际应用 低代码平台开发实践&#xff1a;基于React【文末送书-29】 背景 随着技术的不断进步和业务需求的日益复杂&#xff0c;低代码平台成为现代软件开发领域中备受关注的工具之一。在这个快节奏的时代&#xff0c;…

【QT】Qt Charts概述

目录 1 QtCharts模块 2 图表的主要组成部分 2.1 QChartView的功能 2.2 序列 2.3 坐标轴 2.4 图例 3 一个简单的QChart绘图程序 QtCharts是Qt提供的图表模块&#xff0c;在Qt5.7以前只有商业版才有Qt Charts&#xff0c;但是从Qt5.7开始&#xff0c;社区版本也包含了Qt C…

fortigate 防火墻通過CLT命令行 downgrade降級IOS

​Troubleshooting Tip: Downgrade of FortiOS fails due to BIOS check 通過u盤放入2個文件(Os命名為image.out,配置文件命名為fgt_system.conf),插入 fortigate 防火墻。一般防火墻就自動更新OS,但如果要降級,不會自動更新,需要在CLT裡頭操作一些設置後才能順利降級 …

指针中的回调函数与qsort的深度理解与模拟

今天给大家在更新一下指针类型的知识&#xff0c;这里讲到了一个库函数sqort&#xff0c;以及回调函数的理解。 望喜欢 目录 回调函数 qsort函数 qsort模拟实现 回调函数 回调函数就是⼀个通过函数指针调用的函数。 如果你把函数的指针&#xff08;地址&#xff09;作为参数…

Java - 获取汉字大写首字母输出

背景 有个项目需要将一批字符串的拼音首字母输出并大写&#xff0c;写了个工具类。 实现 需要引入外部jar。 <dependency><groupId>com.belerweb</groupId><artifactId>pinyin4j</artifactId><version>2.5.1</version> </dep…

数字人解决方案——阿里EMO音频驱动肖像生成能说话能唱歌的逼真视频

前言 数字可以分为3D数字人和2D数字人。3D数字人以虚幻引擎的MetaHuman为代表&#xff0c;而2D数字人则现有的图像或者视频做为输入&#xff0c;然后生成对口型的数字人&#xff0c;比如有SadTalker和Wav2Lip。 SadTalker&#xff1a;SadTalker是一种2D数字人算法&#xff0c;…