【数据结构】结构实现:顺序存储模式实现堆的相关操作

news2024/11/25 10:51:20

🚩纸上得来终觉浅, 绝知此事要躬行。
🌟主页:June-Frost
🚀专栏:数据结构

🔥该文章着重讲解了使用顺序结构实现堆的插入和删除等操作。

目录:

  • 🌍二叉树的顺序结构
    • 🔭 堆
  • 🌏 代码实现
    • ✉️ 堆的插入
    • ✉️ 堆的删除
    • ✉️ 其他部分
  • ❤️ 结语

🌍二叉树的顺序结构

 二叉树的顺序存储是指将二叉树中的所有节点按照一定的顺序(一层一层)存储到一个数组中。

 我们可以通过数组下标来表示节点之间的父子关系。

找左孩子节点:leftchild = parent * 2 + 1
找右孩子节点:rightchild = parent * 2 + 2

例如,找B的左孩子 : B的下标 * 2 + 1,得到3 ,即为D。

找父亲节点:parent = ( child -1 )/ 2

例如,找G的父母:(G的下标-1)/ 2 得到 2 ,即为C 。

 需要注意的是,二叉树的顺序存储适用于满二叉树或完全二叉树的情况,对于其他类型的二叉树,顺序存储可能会造成空间浪费访问效率低下的问题。

例如:

 这类二叉树不适合顺序存储,适合链式存储。

🔭 堆

 数据结构中还衍生出了一个结构 —— 堆 , 堆是非线性结构,也是一种完全二叉树。堆的两个常见类型是大堆和小堆。在大堆中,父节点的值总是大于或等于其子节点的值;而在小堆中,父节点的值总是小于或等于其子节点的值。堆通常用数组来实现。
 所以,对于任意一个数组是可以看作一颗完全二叉树,但不一定是堆。


🌏 代码实现

 这里将实现堆的插入和删除,以小堆为例。
 堆的结构特点是:存储结构——数组,逻辑结构——完全二叉树。所以可以定义结构体为:

typedef int HPDataType;
typedef struct Heap
{
	HPDataType* a;
	int size;
	int capacity;
}HP;

✉️ 堆的插入

 插入的需求为:无论如何插入,都必须保持为堆。因为存储结构是数组,所以选择效率更快的尾插,然后再进行调整(插入的数据会影响它的祖先)。
 调整部分有这样的3种场景:

  1. 不会影响祖先


2.影响部分,但不影响到根。


3.影响到全部祖先


注:这种调整是向上调整。时间复杂度为 O(logN)

💫调整的条件:
在这里插入图片描述

📙实现代码:

//交换数据
void Swap(HPDataType* p1, HPDataType* p2)
{
	HPDataType tmp = *p1;
	*p1 = *p2;
	*p2 = tmp;
}
//向上调整
void AdjustUp(HPDataType* a, int child)
{
	int parent = (child - 1) / 2;
	while (child > 0)
	{
		if(a[parent] > a[child])
		{
			Swap(&a[child], &a[parent]);
			child = parent;
			parent = (parent - 1) / 2;
		}
		else
		{
			break;
		}
	}
}
//插入数据
void HeapPush(HP* php, HPDataType x)
{
	assert(php);
	if (php->capacity == php->size)
	{
		int newCapacity = php->capacity == 0 ? 4 : php->capacity * 2;
		HPDataType* tmp = (HPDataType*)realloc(php->a,sizeof(HPDataType) * newCapacity);
		if (tmp == NULL)
		{
			perror("realloc fail");
			exit(-1);
		}
		php->a = tmp;
		php->capacity = newCapacity;
	}
	php->a[php->size] = x;
	php->size++;
    //向上调整
	AdjustUp(php->a, php->size - 1);
}

✉️ 堆的删除

 在堆中,删除栈顶元素才是有意义的,这样经过调整后,根就是次小或次大的值。由于堆的存储结构是数组,尾插尾删的效率很高,所以可以考虑将根和最后一个数组元素交换,然后不断调整。


这样的操作之后,可以发现一个特性:左右子树依旧是小堆。



注:这种调整方式为向下调整,时间复杂度为O(logN)。

💫调整条件:
 当子节点的下标超出数组范围时,说明已经没有子节点了,已经换到了叶子。(针对实现的代码而言,是已经没有了左孩子,因为堆是完全二叉树,自然也就没有右孩子,说明换到了叶子)

📙实现代码:

//向下调整
void AdjustDown(HPDataType* a, int n, int parent)
{
	int child = parent * 2 + 1;//假设左孩子最小
	while (child < n)
	{
		if (child + 1 < n && a[child + 1] < a[child])//注意判断child+1是否越界
		{
			//修正
			child++;
		}
		
		if (a[child] < a[parent])
		{
			Swap(&a[child], &a[parent]);
			//调整
			parent = child;
			child = child * 2 + 1;
		} 
		else
		{
			break;
		}
	}
}
//删除数据
void HeapPop(HP* php)
{
	assert(php);
	assert(php->size > 0);
	Swap(&php->a[0], &php->a[php->size - 1]);
	php->size--;
	AdjustDown(php->a, php->size, 0);
}

✉️ 其他部分

一些简单的接口:

//初始化
void HeapInit(HP* php)
{
	assert(php);
	php->a = NULL;
	php->size = 0;
	php->capacity = 0;
}
//销毁
void HeapDestroy(HP* php)
{
	assert(php);
	free(php->a);
	php->a = NULL;
	php->capacity = php->size = 0;

}
//打印元素
void HeapPrint(HP* php)
{
	assert(php);
	int i = 0;
	for (i = 0; i < php->size; i++)
	{
		printf("%d ", php->a[i]);
	}
	printf("\n");
}
//取堆顶元素
HPDataType HeapTop(HP* php)
{
	assert(php);
	assert(php->size > 0);

	return php->a[0];
}
//判空
bool HeapEmpty(HP* php)
{
	assert(php);

	return php->size == 0;
}

❤️ 结语

 文章到这里就结束了,如果对你有帮助,你的点赞将会是我的最大动力,如果大家有什么问题或者不同的见解,欢迎大家的留言~

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

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

相关文章

什么触控笔好用又便宜?ipad2022手写笔推荐

随着无纸化的广泛使用&#xff0c;和Apple pencil的出现&#xff0c;电容笔逐渐成为生产力的主要部分&#xff0c;像中性笔一样的电容笔&#xff0c;它不止具有小巧的身材&#xff0c;续航和功能都很在线&#xff0c;无论是在学习上还是工作上&#xff0c;电容笔逐渐成为人们缺…

Jenkis 配置钉钉通知

1、安装插件Ding Talk 2、钉钉上的配置 打开钉钉创建机器人&#xff0c;勾选加签&#xff0c;后面jenkins要用到 2.1 webhook -jenins界面要配置的地址&#xff1a;https://。。。。。。 2.2 jenkins 界面的加密地址 3、jenkins界面上的配置 在系统管理中找到安装好的插件&a…

部署docker image到AWS

1. 在AWS里创建ECR 仓库 2. 进入自己的Repository. 然后点击View push commands 3. 记一下这些命令 4. 登陆AWS cloud9 , 利用git clone 你的代码 5. 依次执行步骤3里的所有命令。最后你发现你的ECR里有了一个docker镜像 aws ecr-public get-login-password --region us-eas…

(CVPR-2023)InternImage:利用可变形卷积探索大规模视觉基础模型

InternImage&#xff1a;利用可变形卷积探索大规模视觉基础模型 Title&#xff1a;InternImage: Exploring Large-Scale Vision Foundation Models with Deformable Convolutions paper是上海AI Lab发表在CVPR 2023的工作 paper链接 Abstract 与近年来大规模视觉变换器&#x…

【Vue】入门及生命周期(前后端分离)

目录 一、Vue简介 1、Vue.js是什么 2、库和框架的区别 2.1 库(Library) 2.2 框架(Framework) 3、MVVM的介绍 二、Vue入门 1、Vue快速入门 2、Vue的优势 三、Vue事件 四、Vue生命周期 1、实例 一、Vue简介 1、Vue.js是什么 Vue是一款流行的构建用户界面(UI)的[渐进式…

vue3-admin-element安装

1、直接点此链接进入下载 https://gitee.com/hu-snail/vue3-admin-element-template 2、下载完毕之后是个压缩包&#xff0c;解压 然后直接可以运行到vscode或HBuilder中 3、下载依赖&#xff1a;我使用的npm下载 npm i npm i serve启动 运行&#xff1a;npm run serve …

【力扣】三角形最小路径和

目录 题目 例子 示例 1&#xff1a; 示例 2&#xff1a; 前言 思路 思想 代码 调用的函数 主函数 所有代码 力扣提交的代码 运行结果 小结 题目 给定一个三角形 triangle &#xff0c;找出自顶向下的最小路径和。 每一步只能移动到下一行中相邻的结点上。相邻的结…

分布式事务基础理论

基础概念 什么是事务 什么是事务&#xff1f;举个生活中的例子&#xff1a;你去小卖铺买东西&#xff0c;“一手交钱&#xff0c;一手交货”就是一个事务的例子&#xff0c;交钱和交货必 须全部成功&#xff0c;事务才算成功&#xff0c;任一个活动失败&#xff0c;事务将撤销…

BUU 加固题 AWDP Fix 持续更新中

BUU Ezsql 首先连接上ssh。输入账号密码。 到/var/www/html目录下&#xff0c;源码在里面。 主要是看index.php文件。 <?php error_reporting(0); include dbConnect.php; $username $_GET[username]; $password $_GET[password]; if (isset($_GET[username]) &&am…

shared library

原文、 shared library compatible vs incompatible compatible library 函数的工作场景没有变化 所有的函数对全局变量和返回参数产生相同的影响所有的函数继续返回相同的结果值提升性能 fix bugs 没有api 被删除可以有新的api加入 export 的结构体没有变化 违反以上各条的…

c++八股day2-虚函数表和虚函数表指针的创建时机

虚函数表和虚函数表指针的创建时机。 背景&#xff1a;用来实现多态&#xff08;包括静态多态和动态多态&#xff09;&#xff0c;多态的原理就是虚函数表和虚函数表指针 虚函数表的创建时机&#xff1a; a.什么时候生成的&#xff1f;编译器编译的时候声生成的&#xff0c;…

筑梦未来,与“EYE”同行——蔡司镜片X肇庆爱尔眼科医院走进石群小学

不知不觉&#xff0c;蔡司光学这项传递护眼理念、营造公益氛围的助童活动已步入第十个年头。从一开始的“孤军奋战”&#xff0c;到现如今拥有汇聚眼视光领域同行的社会号召力&#xff0c;品牌为青少年近视管理方案绘就了清晰的发展蓝图&#xff0c;旨在用蔡司镜片帮助广大青少…

Java(运算符+循环)万字超详细介绍 (囊括了按位,异或,for,while等基础和疑难知识)

【本节目标1】熟练掌握运算符 【本章目标2】熟练掌握循环 万字讲解&#xff0c;十分详细&#xff0c;有大量&#xff08;简单&#xff09;代码帮助理解和大量的&#xff08;简单&#xff09;举例与总结。 1.运算符 1.什么是运算符 计算机最基本的用途之一就是执行数学运算…

shopee——排序模型AUC还能涨吗?

文章目录 CBMRMultiCBMRSample Weight Assignment多任务推荐模型 CBMR MultiCBMR Sample Weight Assignment Click-aware Structure Transfer with Sample Weight Assignment for Post-Click Conversion Rate Estimation 每个用户的top-k 邻居每个商品的top-k 邻居平滑处理并构…

Windows【工具 04】WinSW官网使用说明及实例分享(将exe和jar注册成服务)实现服务器重启后的服务自动重启

官方Github&#xff1b;官方下载地址。没有Git加速的话很难下载&#xff0c;分享一下发布日期为2023.01.29的当前最新稳定版v2.12.0网盘连接。 包含文件&#xff1a; WinSW-x64.exesample-minimal.xmlsample-allOptions.xml 链接&#xff1a;https://pan.baidu.com/s/1sN3hL5H…

02_elasticsearch 核心概念

02_elasticsearch 核心概念 1、lucene和elasticsearch的前世今生2、elasticsearch的核心概念 1、lucene和elasticsearch的前世今生 1、lucene和elasticsearch的前世今生 lucene&#xff1a;最先进、功能最强大的搜索库。但是直接基于lucene开发&#xff0c;非常复杂&#xff…

Idea安装webservice插件

打开Idea的settings菜单&#xff0c;选择Plugins&#xff0c;模糊搜索"Web Ser"&#xff0c;安装以下3个红框内插件&#xff1a; 安装好以上3个插件后&#xff0c;就可以根据需求生成webservice客户端或者webservice服务端了。

【C语言】进阶——指针

目录 ①(●◡●)前言 1.字符指针 ✌字符指针和数组笔试题 2.指针数组 和数组指针 &#x1f44a;指针数组 &#x1f44a;数组指针 &#x1f44a;&数组名和数组名 3.数组传参和指针传参 &#x1f44a;一维数组传参 &#x1f44a;二维数组传参 &#x1f44a;一级…

Gmail邮箱注册情况及最新动态

在中国大陆地区&#xff0c;对于是否可以注册Gmail邮箱一直存在一定的限制和讨论。准确来说&#xff0c;中国大陆地区的用户目前无法直接访问和注册Gmail邮箱。由于某些政策和技术原因&#xff0c;中国政府对于一些外国的网站和服务实施了网络封锁与限制。因此&#xff0c;中国…

聊聊Go语言的向前兼容性和toolchain规则

Go语言在发展演进过程中一直十分注重向后兼容性(backward compatibility)&#xff0c;在Go 1.0版本发布[1]之初就发布了Go1兼容性承诺[2]&#xff0c;简单来说就是保证使用新版本Go(比如Go 1.21版本[3])可以正常编译和运行老版本的Go代码(比如使用Go 1.18版本[4]语法编写的go代…