堆的数组实现

前言

本次博客来讲解一下堆的数组实现,好吧还是会结合图例,让大家理解

堆的定义

什么是堆?

堆是一颗完全二叉树。它的性质是父节点一定大于或者一定小于子节点

每一个结点都要满足这个性质就是堆

堆的特性是堆顶的数据一定是最大或最小,最大为大堆,最小为小堆

看图

那我们如何实现堆呢?

我们可以注意堆是一个完全二叉树,我们可以使用一个数组来模拟完全二叉树

那么如何使用数组实现完全二叉树

使用数组实现完全二叉树

OK,首先我们可以通过数组下标,来确定节点,只要能够得到父子关系就可以遍历整个完全二叉树,看图吧

OK,那么咱么可不可以实现一下前序遍历呢

使用递归和非递归

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#define N 10
//适用于满二叉树和完全二叉树
typedef struct BianryTree {
	int a[N];
}BT;
void InitBinaryTree(BT* bt,int cursize)
{
	if (cursize >= N)
		return;
	bt->a[cursize] = cursize;
	InitBinaryTree(bt,cursize*2+1);
	InitBinaryTree(bt,cursize*2+2);
}
void TraversalTree(BT* bt, int cursize)
{
	if (cursize >= N)
		return;
	printf("%d ", bt->a[cursize]);
	TraversalTree(bt, cursize * 2 + 1);
	TraversalTree(bt, cursize * 2 + 2);
}
int main()
{
	BT* bt = (BT*)malloc(sizeof(BT));
	InitBinaryTree(bt,0);
	TraversalTree(bt, 0);
	return 0;
}

上面是前序遍历属于递归遍历

接下来看非递归遍历,其实可以

void TraversalTree(BT* bt, int cursize)
{
	while (cursize < N)
		printf("%d ", bt[cursize++]);
}

只需改一改就好,这里相当于层序遍历

那么使用数组去实现完全二叉树是可行的

数组实现堆

我们先看看堆有哪些接口,然后一一实现

看一看头文件吧

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>
typedef int HpDatatype;
typedef struct Heap {
	HpDatatype* a;
	int capacity;
	int size;
}HP;
void IintHeap(HP* hp);
void PushHeap(HP* hp, HpDatatype x);
void PopHeap(HP* hp);
HpDatatype TopHeap(HP* hp);
void DestroyHeap(HP* hp);
bool EmptyHeap(HP* hp);
int SizeHeap(HP* hp);

 OK

先实现几个简单的   初始化,没什么好说的

void IintHeap(HP* hp)
{
	hp->a = NULL;
	hp->capacity = 0;
	hp->size = 0;
}

  返回堆大小,也没有什么好说的

int SizeHeap(HP* hp)
{
	assert(hp);
	return hp->size;
}

返回堆顶

HpDatatype TopHeap(HP* hp)
{
	assert(hp);
	assert(hp->size > 0);
	return hp->a[0];
}

判空

bool EmptyHeap(HP* hp)
{
	assert(hp);
	return hp->size == 0;
}

销毁堆

void DestroyHeap(HP* hp)
{
	assert(hp);
	free(hp->a);
	hp->capacity = 0;
	hp->size = 0;
}

插入数据

void PushHeap(HP* hp, HpDatatype x)
{
	assert(hp);
	//检查容量
	if (hp->size == hp->capacity)
	{
		int newcapacity = hp->capacity == 0 ? 4 : hp->capacity * 2;
		HpDatatype* temp = (HpDatatype*)realloc(hp->a, sizeof(HpDatatype) * newcapacity);
		if (temp == NULL)
		{
			printf("realloc fail\n");
			return;
		}
		else
		{
			hp->a=temp;
			hp->capacity = newcapacity;
		}
	}
	//向上调整法
	hp->a[hp->size++] = x;
	AdjustUp(hp->a,hp->size-1);
}

这个代码的逻辑是,每插入一个数据,对该数据进行向上调整法

那么向上调整法可以确保,每插入一个数据,该数组保持为堆

那么现在我们画图来理解什么是向上调整法

OK,下面是向上调整法

void AdjustUp(HpDatatype* a, int child)
{
	//这里的向上调整法是调整它的祖先
	while (child > 0)
	{
		int parent = (child - 1) / 2;
		if (a[child] < a[parent])
		{
			int temp = a[child];
			a[child] = a[parent];
			a[parent] = temp;
			child = parent;
		}
		else
		{
			break;
		}
	}
}


删除一个数据

void PopHeap(HP* hp)
{
	assert(hp);
	assert(hp->a > 0);
	swap(&hp->a[0], &hp->a[hp->size - 1]);
	//向下调整法
	AdjustDown(hp->a, 0, hp->size);
	hp->size--;
}

 我们要删除的是堆顶的数据

所以让第一个数据与最后一个数据交换,size--

此时,第一个节点的左子树和右子树都是堆,我们只要再调整一下根节点即可

这种调整叫做向下调整法

这里就不画图了,有点麻烦

直接看代码吧

void AdjustDown(HpDatatype* a, int start, int end)
{
	int parent = start;
	//假设法,假设左孩子更接近目的
	int child = parent * 2 + 1;
	end = end - 1;
	while (child <end)
	{
		if (child + 1 < end && a[child + 1] < a[child])
			child++;
		if (a[parent] > a[child])
		{
			swap(&a[child],&a[parent]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
			break;
	}
}

 这里的逻辑就是,先使用假设法让child唯一

然后,比对a[child]和a[parent]的大小 满足条件则交换

大堆 a[child]>a[parent]    小堆 a[child]<a[parent]

如果不满足条件,直接结束.

测试堆

看图吧

 这是小堆,所以是升序,也算是完成了

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

数据不出境的SSL证书

说到SSL证书&#xff0c;大部分用户对于SSL证书的作用还是有着或多或少的了解的。比如&#xff1a; 使用SSL证书可以实现网站的加密访问&#xff0c;相对于数据传输的安全性来说&#xff0c;https访问可以杜绝http的明文访问&#xff1b; 提升品牌形象&#xff0c;安装SSL证书…

vue3 + ts中,element-plus组件通过ref引用组件内方法,显示提示

在vue3 ts 项目中&#xff0c;我们通过ref引用element-plus组件内部方法时&#xff0c;编辑器没有提示信息&#xff0c;通常我们都是如下写法 这里想进行一下表单校验&#xff0c;需要引用el-form组件中的validate方法&#xff0c;从这里可以看出是没有给相应的提示信息的。这…

洛谷模板.Floyd的深度理解(python)

先上代码&#xff1a; n, m map(int, input().split()) edge [ [float(inf)]*n for _ in range(n)] for i in range(m):u, v, w map(int, input().split())edge[u-1][v-1] min(edge[u-1][v-1], w)edge[v-1][u-1] min(edge[v-1][u-1], w) for i in range(n):edge[i][i] 0…

小程序(四)

十四、分包加载 &#xff08;一&#xff09;普通分包与主包 随着项目越来越大&#xff0c;为了用户更好的体验&#xff0c;小程序引用了分包技术&#xff0c;分包技术将tabBar页面及一些全局使用的静态资源&#xff0c;放到主包中&#xff0c;开发者可以根据需要添加分包&…

三无跨考,上岸热门211?

这个系列会邀请上岸学长学姐进行经验分享~ 今天分享经验的同学也是梦马班的学员&#xff0c;一战高分上岸福州大学&#xff01; 经验分享 一战零基础跨考福州大学866&#xff0c;初试395&#xff0c;信号141&#xff0c;最后本部录取排名前十。各位要报考福州大学的学弟学妹…

Win7远程桌面连接不上:原因及专业解决方案

Win7远程桌面连接作为一种方便的工具&#xff0c;使得用户可以从一台计算机远程访问和操作另一台计算机。然而&#xff0c;有时用户可能会遇到Win7远程桌面连接不上的情况&#xff0c;这可能是由于多种原因导致的。 一、原因分析 1. 网络设置问题&#xff1a;确保计算机与远程…

SpringBoot之远程调用的三大方式

为什么要使用远程调用&#xff1f; SpringBoot不仅继承了Spring框架原有的优秀特性&#xff0c;而且还通过简化配置来进一步简化了Spring应用的整个搭建和开发过程。在Spring-Boot项目开发中&#xff0c;存在着本模块的代码需要访问外面模块接口&#xff0c;或外部url链接的需求…

国网645协议报文解析软件

本文分享一款支持国网DL645-2007规约的报文解析软件&#xff0c; 链接: https://pan.baidu.com/s/1ngbBG-yL8ucRWLDflqzEnQ 提取码: y1de 主界面如下图所示&#xff1a; 本解析软件同时内嵌规约文档&#xff0c;支持一键打开文档&#xff0c;功能如下&#xff1a; 同时支持模…

SAP CS07复制BOM简介

在比较大型的集团公司中会应用到这样一个场景,所有的BOM都是由总部研发统一管控,然后在下发到下属的工厂进行生产,当发生变更的时候BOM也是会随之进行变更。 同样的在相同的两家工厂中,使用的是一套的设计方案,并且当物料发起变更的时候BOM也要随之进行变更处理。 在对BO…

【软件的安装与基本设置】AD21软件的PCB规则设置

在绘制PCB之前&#xff0c;要进行规则的创建&#xff0c;因为在绘制PCB的过程中&#xff0c;难免会出现很多错误&#xff0c;所以需要先对绘制PCB创建规则&#xff0c;即所有的打孔&#xff0c;走线&#xff0c;铺铜都要基于电气性能规则去设计&#xff0c;等到后期&#xff0c…

win10共享文件夹到ubuntu22

win10共享文件夹 新建用户 新建用户、设置密码。避免共享给EveryOne&#xff0c;导致隐私问题。 点击左下角的开始菜单&#xff0c;选择“设置”&#xff08;WinI&#xff09;打开设置窗口。在设置窗口中&#xff0c;搜索或直接点击“账户”进入账户设置。在账户设置中&…

Android Compose 五:常用组件 TextField

1、基本使用 1.1 随便用用 TextField(value "吃吃吃", onValueChange {})结果 点击输入框可以弹出软键盘光标显示正常 到文字最后位置文字 “吃吃吃” 无法删除输入文本无法变更 1.2 使用 val text remember {mutableStateOf("这一个输入框") } Te…

微信小程序如何变现

微信小程序有多种变现方式&#xff0c;以下是一些主要的方法&#xff1a; 广告变现&#xff1a;在小程序中嵌入广告&#xff0c;通过点击、曝光等手段获取收益。这是一种非常普遍的变现方式&#xff0c;尤其适合流量较大、用户活跃度较高的小程序。 电商变现&#xff1a;通过…

Vitis Platform Methodology

Vitis Platform Methodology

2024年开抖店都需要做哪些准备?这些条件缺一不可

大家好&#xff0c;我是电商花花。 作为目前国内最受欢迎的短视频电商平台&#xff0c;抖音将成为众多创业者的首选平台。 在往年我们都知道抖音小店市场很多&#xff0c;红利很大&#xff0c;利润大&#xff0c;不少人都通过抖音小店实现了脱贫&#xff0c;也有部分上班族获…

品鉴中的礼仪习俗:如何遵循正确的红酒品鉴礼仪

在品鉴云仓酒庄雷盛红酒时&#xff0c;遵循正确的礼仪习俗不仅能展现个人的修养&#xff0c;还能更好地领略葡萄酒的风味。下面我们将探讨红酒品鉴中的礼仪习俗。 首先&#xff0c;当我们拿起酒杯时&#xff0c;应该注意不要晃动酒杯&#xff0c;以免扰动其中的酒液。同时&…

接口自动化-requests库

requests库是用来发送请求的库&#xff0c;本篇用来讲解requests库的基本使用。 1.安装requests库 pip install requests 2.requests库底层方法的调用逻辑 &#xff08;1&#xff09;get / post / put / delete 四种方法底层调用 request方法 注意&#xff1a;data和json都…

品鉴中的食物搭配:如何创造美味的红酒与食物组合

品鉴云仓酒庄雷盛红酒时&#xff0c;食物搭配是一个不可忽视的环节。通过巧妙的搭配&#xff0c;红酒与食物可以相互衬托&#xff0c;呈现出更加美妙的风味。下面就让我们一起探讨如何创造美味的红酒与食物组合。 首先&#xff0c;了解红酒与食物的搭配原则是关键。一般来说&a…

本特利330104-00-20-05-02-00振动监测输出模块在PLC系统中的应用与集成

本特利330104-00-20-05-02-00振动监测输出模块在PLC系统中的应用与集成 一、引言 在现代工业自动化领域中&#xff0c;机械设备的振动监测是确保设备稳定运行、预防故障发生的重要手段之一。本特利&#xff08;Bently Nevada&#xff09;作为全球知名的振动监测解决方案提供商…

flowable工作流设置审批人为指定角色+部门的实现方式

一、绘制流程图页面配置 1、指定固定审批角色组织的实现 如上图红框部分&#xff0c;需要修改此处为需求对应。比如此时红框不支持指定某个部门下的指定角色这种组合判断的审批人。则需要修改页面变成选完角色同时也选择上部门统一生成一个group标识。 修改完后&#xff0c;生…