堆的向上和向下调整

news2024/10/4 6:46:11

堆的物理结构和逻辑结构是什么?

堆如何插入数据和删除数据?为什么?

向上调整和向下调整的要求是啥? 

文中不理解的可以先看堆的代码和基础知识-CSDN博客

也欢迎评论区一起讨论

1.堆的物理结构和逻辑结构 

我们的堆是用数组实现的

因此堆的物理结构是数组

但是堆的逻辑结构确是二叉树

2.插入数据和向上调整

但是我们再思考一个问题就是,当我们有一个堆的时候,怎么是插入数据呢?

以上面画的那个图为例,我们要插入一个 数据,并且还要保持堆的特性(父节点大于子节点)

我们该如何调整呢? 

但是我们要首先要明确一个点就是除了我们插入数据,其他数据,其他数据成堆

这个就是向上调整的使用条件 

设我们要插入数据,只能在物理结构上插入到数组的最后一个,再对插入的数据进行调整

也称为向上调整

这样的好处是我们不会对前面的数据产生影响(前面的数据成堆)

然后我们要进行调整了

这个地方假设我们插入的是99,明显就需要调整,但是只有这个数据是有问题的,因此我们只用对这个数据和它的祖先进行遍历调整就可以了

那么遍历什么时候停止呢?

1.就是如上图,我把插入节点的祖宗节点全部遍历完(这个就是上面那个图停止的原因)

2.就是当插入的数据符合堆的要求(父节点大于子节点)

那么我们就可以开始写代码了

首先就是子节点和父节点的关系是什么呢?

所以

父节点=(子节点-1)/2

我们就可以开始写向上调整的代码了

// 除了child这个位置,前面数据构成堆
void AdjustUp(HPDataType* a, int child)
{
	int parent = (child - 1) / 2;
	//while (parent >= 0)
	while (child > 0)//判断遍历是否结束
	{
		if (a[child] > a[parent])//不满足堆的要求,进行调整
		{
			Swap(&a[child], &a[parent]);//交换父子节点
			child = parent;
			parent = (child - 1) / 2;
		}
		else//满足,调整结束
		{
			break;
		}
	}
}

我们思考一下就是如果改成while(parent>=0)是否也可以

答案是未必

当child等于0的时候parent=(child-1)/2=-1/2=0;

这个时候我们遍历结束但无法跳出while循环了

我们向上调整写完了,那么我们就可以接着写如何插入数据了,那就非常easy了

void HeapPush(HP* php, HPDataType x)
{
	assert(php);

	if (php->size == php->capacity)
	{
		HPDataType* tmp = (HPDataType*)realloc(php->a, sizeof(HPDataType) * php->capacity * 2);
		if (tmp == NULL)
		{
			perror("realloc fail");
			return;
		}
		php->a = tmp;
		php->capacity *= 2;
	}

	php->a[php->size] = x;
	php->size++;

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

 上面大部分代码基本都是老朋友了,如果不熟那就先去复习一下前面的链表和顺序表,这个地方我解释一下,这个地方向上调整这个函数为啥要传php->size-1而不是php->size

我们先来看向上调整函数里面我们交换的是什么?

Swap(&a[child], &a[parent]);

交换的是两个数组的地址啊,数组的下标是从0开始的,但是size代表的是节点个数,是从1开始的啊,所以这个地方child的下标就是size-1了

3.删除节点删什么节点

这个地方我们以大端为例,小端同理

我们接下来再看怎么删除节点,我们先来想想我们删除节点是删除叶节点还是端节点?

当然肯定是端节点啊,为什么啊?

首先我们要思考一个问题,就是我们的堆是用来干嘛的?

其中很重要一个作用是用来排序的啊!

那么我们堆满足的性质是什么?

是所有的父节点都大于子节点

但是我们能不能保证兄弟节点谁大谁小啊,这个是未知的

但是如果我们要排序我们去删除叶节点,我们怎么确定这个叶节点是最大的节点啊(你怎么知道它的兄弟节点一定比它大啊?)

这样我们无法达到排序的功能

但是我们的端节点,它没有兄弟节点,只有子孙节点,这也就意味着它是所有数里面最大的,我把端点删了,得到的下一个端点不就是第二大的数吗。

以此类推,我们就可以得到第三大,第四大等等的数了吗?不就可以实现排序了吗?

4.删除节点和向下调整

但是这个地方我们要记住一个点,后面会用上,就是我们把端点删除后,它的左右子孙端点会形成新的堆

这个也就是向下调整的使用前提

那我们思考一下,我们删除了端点,接下来改怎么调整呢?

端点删除之后的左右子孙端点会形成新的堆,那我们最好就不要破坏这个结构,

就不要直接把这两个端点最大的那个设为新的端点,因为这样有可能会导致后面的数据不构成堆,会非常麻烦,我们就直接把最后一个节点和端点交换,

然后再对端点进行free就完成删除了,那么删除后,我们还要对这个堆进行调整,这个时候就是向下调整了

向下调整这个地方我们以大堆为例子

我们把端点和叶节点交换位置后, 我们要调整,要保证父节点大于子节点,

因为我们只用把交换的那个数据   从上到下   和  其子节点最大的值   进行比较,如果比它们小,那就交换位置

,遍历一遍就可以了

停下来有两个条件

1.第一就是遍历完了,和叶节点比较完了

2.第二就是满足这个数据大于它的两个子节点最大的一个了(上面画的图属于这种)

因此我们就可以写向下调整的代码了

// 左右子树都是大堆/小堆
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;
		}

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

同样,删除端点的代码也可以写了

oid HeapPop(HP* php)
{
	assert(php);
	assert(!HeapEmpty(php));

	// 删除数据
	Swap(&php->a[0], &php->a[php->size - 1]);
	php->size--;

	AdjustDown(php->a, php->size, 0);
}

 这个地方的size-1而不是size的原因见上文

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

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

相关文章

计算机毕业设计 视频点播系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…

【AI知识点】维度灾难(curse of dimensionality)

维度灾难&#xff08;curse of dimensionality&#xff09; 是指在处理高维数据时&#xff0c;随着维度的增加&#xff0c;数据的性质和空间结构变得越来越复杂&#xff0c;导致许多常见的算法和技术在高维空间中效率低下或效果变差的问题。 这个概念最早是由Richard Bellman在…

RabbitMQ篇(基本介绍)

目录 一、MQ 1. 什么是MQ 2. 为什么要用MQ【业务场景】 2.1. 异步 2.2. 应用解耦 2.3. 流量削峰 3. MQ的分类 &#xff08;1&#xff09;ActiveMQ &#xff08;2&#xff09;Kafka &#xff08;3&#xff09;RocketMQ &#xff08;4&#xff09;RabbitMQ 4. MQ 的选…

计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-02

计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-02 1. APM: Large Language Model Agent-based Asset Pricing Models Authors: Junyan Cheng, Peter Chin https://arxiv.org/abs/2409.17266 APM: 基于大型语言模型的代理资产定价模型&#xff08;LLM Agent-b…

2、项目配置设计(上)

文章目录 前言一、配置文件功能需求二、web工程设计思路三、Config实现思路 前言 配置文件作用&#xff1a;把需要经常修改的参数&#xff0c;从代码中分离出来,单独管理&#xff0c;方便后期维护。 开发一个web应用&#xff0c;肯定需要一些基础性的配置信息&#xff0c;这些信…

骨架屏 (懒加载优化)

骨架屏 &#xff08;懒加载优化&#xff09; 即便通过 Webpack 的按需加载、CDN 静态资源缓存 和 代码分割 等技术来减少首屏的代码体积&#xff0c;首屏加载时的白屏时间&#xff08;也称为首屏等待时间&#xff09;仍然可能存在&#xff0c;尤其在网络条件较差或页面内容复杂…

【设计模式-解释模式】

定义 解释器模式是一种行为设计模式&#xff0c;用于定义一种语言的文法&#xff0c;并提供一个解释器来处理该语言的句子。它通过为每个语法规则定义一个类&#xff0c;使得可以将复杂的表达式逐步解析和求值。这种模式适用于需要解析和执行语法规则的场景。 UML图 组成角色…

基于Springboot vue应急物资供应管理系统设计与实现

博主介绍&#xff1a;专注于Java&#xff08;springboot ssm 等开发框架&#xff09; vue .net php python(flask Django) 小程序 等诸多技术领域和毕业项目实战、企业信息化系统建设&#xff0c;从业十五余年开发设计教学工作☆☆☆ 精彩专栏推荐订阅☆☆☆☆☆不然下次找…

【硬件模块】HC-SR04超声波模块

HC-SR04超声波模块实物图 工作参数 探测距离&#xff1a;2~600cm 探测精度&#xff1a;0.1cm1% 感应角度&#xff1a;<15 输出方式&#xff1a;GPIO 工作电压&#xff1a;DC 3~5.5V 工作电流&#xff1a;5.3mA 工作温度&#xff1a;-40~85℃ 引脚接线 HC-SR04MCU备注VC…

Golang | Leetcode Golang题解之第454题四数相加II

题目&#xff1a; 题解&#xff1a; func fourSumCount(a, b, c, d []int) (ans int) {countAB : map[int]int{}for _, v : range a {for _, w : range b {countAB[vw]}}for _, v : range c {for _, w : range d {ans countAB[-v-w]}}return }

04-SpringBootWeb案例(下)

3. 员工管理 完成了部门管理的功能开发之后&#xff0c;我们进入到下一环节员工管理功能的开发。 基于以上原型&#xff0c;我们可以把员工管理功能分为&#xff1a; 分页查询&#xff08;今天完成&#xff09;带条件的分页查询&#xff08;今天完成&#xff09;删除员工&am…

Pikachu-Sql Inject-数字型注入(GET)

一、、破解 SQL 查询语句中的字段数 ?id1 order by 3 -- // -- 是注释&#xff0c; 加号 在MySQL中会转成空格 order by 1 &#xff0c;by 数字几&#xff0c;就是按照第几列进行排序&#xff1b;如果没有这一行&#xff0c;则报错 如&#xff1a;以下语句&#xff0c;根据…

QT学习笔记1(QT和QT creator介绍)

QT学习笔记1&#xff08;QT和QT creator介绍&#xff09; Qt 是一个跨平台的应用开发框架&#xff0c;主要用于图形用户界面&#xff08;GUI&#xff09;应用的开发&#xff0c;但也支持非GUI程序的开发。Qt 支持多种平台&#xff0c;如Windows、macOS、Linux、iOS和Android&a…

Servlet的生命周期及用户提交表单页面的实现(实验报告)

一、实验目的、要求 1. 掌握Servlet的定义&#xff0c;即Servlet是运行在服务器端的Java程序&#xff0c;用于扩展服务器的功能。 2. 学习和掌握在开发环境中搭建Servlet应用所需的工具&#xff0c;如Tomcat服务器、IDEA等。 二、实验内容 根据本章所学知识&#xff0c;实验…

linux第一课:下载与安装

这是我的个人复习笔记&#xff0c;草稿箱字太多会卡就发这了&#xff0c;欢迎大家阅读。 Kali Linux&#xff0c;黑客必备神器。跟着我&#xff0c;带你从入门到入狱&#xff01; 第一课&#xff0c;下载与安装。 第一步&#xff1a; 在官网下载Centos镜像&#xff1a;http…

(2025)408考研:王道操作系统文件管理强化

写在最前面,需要pdf的请资源里下载,已经排版好了,这里不知道为什么粘贴上来排版这么难看!!! 某一个分区进行格式化的时候,这个分区的文件系统就被建立了,一旦这个文件系统建立完后,就确定了文件系统使用的什么样的物理结构。 操作系统引导: 主存分为两部分,RAM和RO…

人体目标检测数据集 18000张 人体 带标注voc yolo

人体目标检测数据集 18000张 人体 带标注voc yolo 继续 人体目标检测数据集介绍 数据集名称 人体目标检测数据集 (Human Detection Dataset) 数据集概述 该数据集专为训练和评估基于YOLO系列目标检测模型&#xff08;包括YOLOv5、YOLOv6、YOLOv7等&#xff09;而设计&#…

vue-cli老项目继续优化:json压缩神器 compress-json

前言 上文讲到一个 vue-cli 带脚本生成内容的老项目的打包时间已经从 40min &#xff0c;优化到 12min &#xff0c;再到 9min 。 还有可以考虑的方式包含缩小脚本体积、依赖分包、构建的缓存等等。 那么本文就来讨论缩小脚本体积的方式。 分析 前文已知&#xff0c;生成的…

螺狮壳里做道场:老破机搭建的私人数据中心---Centos下Docker学习06(Docker网络连接)

如果要搭建基于docker的私人DC&#xff0c;除了虚拟机网络连接外&#xff0c;就得掌握docker的网络连接。磨刀不误砍柴工&#xff0c;或者说工欲善其事必先利其器&#xff0c;我们先学学典型的docker的网络连接方式。Docker的网络连接有四种&#xff1a;bridge、none、containe…

jmeter学习(2)变量

1&#xff09;用户定义的变量 路径&#xff1a;添加-》配置元件-》用户定义的变量 用户定义的变量是全局变量&#xff0c;可以跨线程组被调用&#xff0c;但在启动运行时获取一次值&#xff0c;在运行过程中不再动态获取值。 2&#xff09;用户参数 路径&#xff1a;…