堆的实现(堆的插入、堆的删除等)超级全

news2024/11/15 5:09:10

堆的实现(堆的插入、堆的删除等)超级全

在这里插入图片描述

文章目录

  • 堆的实现(堆的插入、堆的删除等)超级全
    • 一、前期基础知识
      • 1.树结构
        • ①树的定义
        • ②树的相关概念
        • ③二叉树
        • ④满二叉树和完全二叉树
          • a.满二叉树
          • b.完全二叉树
        • ⑤二叉树的性质
        • ⑥二叉树顺序结构的存储和链式结构的存储
          • a.顺序结构存储
          • b.链式结构存储
      • 2.堆结构
    • 二、堆结构/二叉树顺序结构存储的实现
      • 1.堆的初始化
      • 2.堆的销毁
      • 3.堆的插入
      • 4.堆的删除
      • 5.取堆顶数据
      • 6.堆的数据个数
      • 7.堆的判空

一、前期基础知识

1.树结构

①树的定义

树是一种非线性的数据结构,它是由n(n>=0)个有限结点组成一个具有层次关系的集合。把它叫做树是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。

②树的相关概念

在这里插入图片描述
节点的度:一个节点含有的子树的个数称为该节点的度; 如上图:A的为6。
叶节点或终端节点:度为0的节点称为叶节点; 如上图:B、C、H、I…等节点为叶节点。
非终端节点或分支节点:度不为0的节点; 如上图:D、E、F、G…等节点为分支节点。
树的度:一棵树中,最大的节点的度称为树的度; 如上图:树的度为6。
节点的层次:从根开始定义起,根为第1层,根的子节点为第2层,以此类推。
树的高度或深度:树中节点的最大层次; 如上图:树的高度为4。
n个结点的树,有n-1条边。

一棵树有以下三部分组成
根节点,无前驱结点。
叶结点,度为0,又称终端结点
非终端节点,分支节点,度不为0

一棵树是由根节点和n颗子树构成的,子树一定不能相交,除了根节点外,每一个结点都有且仅有一个父节点。

如果不是树结构,那就是图结构。

③二叉树

每一个结点的度不一定都是2,整个二叉树里不存在度大于2的结点。

  1. 或者为空
  2. 由一个根节点加上两棵别称为左子树和右子树的二叉树组成

在这里插入图片描述
在这里插入图片描述

④满二叉树和完全二叉树
a.满二叉树

满二叉树
一个二叉树,如果每一个层的结点数都达到最大值,则这个二叉树就是满二叉树。也就是说,如果一个二叉树的层数为K,且结点总数是2 ^ k - 1 ,则它就是满二叉树。

b.完全二叉树

完全二叉树
前(n - 1)层是满的
最后一层不满,但是从左到右必须连续排布,最少1个,最多2 ^ (n - 1)个。

⑤二叉树的性质
  1. 若规定根节点的层数为1,则一棵非空二叉树的第i层上最多有2 ^ (i - 1)个结点.
  2. 若规定根节点的层数为1,则深度为h的二叉树的最大结点数是2 ^ h - 1
  3. 对任何一棵二叉树, 如果度为0其叶结点个数为n0 , 度为2的分支结点个数为n2 ,则有n0 = n2 + 1
  4. 若规定根节点的层数为1,具有n个结点的满二叉树的深度,h= log2底(n + 1)。(ps: 是log以2为底,n+1为对数)
  5. 将二叉树的每一个结点按层次从0到n编号:
    0
    1 2
    3 4 5 6
    7 8 (7,8为3的子节点)
    举个例子,这就是一个完全二叉树,0 = (1 - 1) / 2, 0 = (2 - 1) / 2,所以parent = (child - 1) / 2, leftchild = parent * 2 + 1, rightchild = leftchild + 1。
    但是注意,一定要在范围里。
⑥二叉树顺序结构的存储和链式结构的存储
a.顺序结构存储

顺序结构存储就是使用数组来存储,一般使用数组只适合表示完全二叉树因为不是完全二叉树会有空间的浪费。而现实中使用中只有堆才会使用数组来存储。二叉树顺序存储在物理上是一个数组,在逻辑上是一颗二叉树。
在这里插入图片描述

b.链式结构存储

二叉树的链式存储结构是指,用链表来表示一棵二叉树,即用链来指示元素的逻辑关系。 通常的方法是链表中每个结点由三个域组成,数据域和左右指针域,左右指针分别用来给出该结点左孩子和右孩子所在的链结点的存储地址 。链式结构又分为二叉链和三叉链,二叉链就是两个指针+数据域,三叉链就是两个指针+指向父节点+数据域,我们暂时先不做重点讲解,后续笔者会进行讲解。

2.堆结构

1.一段连续的数组数据看作完全二叉树
2.必须是小堆或者大堆
小堆:任意一个父节点小于等于子节点
大堆:任意一个父节点大于等于子节点

typedef int HPDataType;

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

大家不妨再思考一下,数据结构的目的到底是什么,就是为了方便我们在内存中管理数据,再加上一些可以实现对这段数据进行操作的接口函数来实现我们的目的。

二、堆结构/二叉树顺序结构存储的实现

1.堆的初始化

void HPIni(HP* php)
{
	assert(php);
	php->a = NULL;
	php->size = 0;
	php->capacity = 0;
}

2.堆的销毁

void HPDestroy(HP* php)
{
	assert(php);
	free(php->a);
	php->a = NULL;
	php->size = 0;
	php->capacity = 0;
}

3.堆的插入

void Swap(HPDataType* p1, HPDataType* p2)
{
	assert(p1 && p2);
	HPDataType tmp = *p1;
	*p1 = *p2;
	*p2 = tmp;
}

void HPAdjustUp(HPDataType* p, int child)
{
	assert(p);
	int parent = (child - 1) / 2;
	while (child > 0)
	{
		if (p[child] < p[parent])
		{
			Swap(( & p[child]), ( & p[parent]));
			child = parent;
			parent = (parent - 1) / 2;
		}
		else
		{
			break;
		}
	}
}

void HPPush(HP* php, HPDataType x)
{
	assert(php);
	if (php->size == php->capacity)
	{
		int newcapacity = php->capacity == 0 ? 4 : 2 * (php->capacity);
		HPDataType* tmp = (HPDataType*)realloc(php->a, newcapacity * sizeof(HPDataType));
		if (tmp == NULL)
		{
			perror("realloc");
			exit(-1);
		}
		php->a = tmp;
		php->capacity = newcapacity;
	}
	php->a[php->size] = x;
	php->size++;
	HPAdjustUp(php->a, (php->size - 1));
}

当你插入一个新的数据到堆里后,一定要记得你的结构实际是一个二叉树,而且以小堆为例,如果你插入的数据,比这个结点的父节点小,那就需要向上调整。

4.堆的删除

void HPAdjustDown(HP* p, int parent)
{
	assert(p);
	int child = parent * 2 + 1;//使用假设法
	while (child < (p->size))
	{
		if ((child + 1 < p->size) && (p->a[child + 1] < p->a[child]))
		//这个真的很重要,值得反复思考,进行交换
		{
			child = child + 1;
		}
		if (p->a[child] < p->a[parent])
		{
			Swap(&(p->a[child]), &(p->a[parent]));
			parent = child;
			child = child * 2 + 1;
		}
		else
		{
			break;
		}
	}
}

void HPPop(HP* php)
{
	assert(php);
	assert(php->size > 0);
	Swap(&(php->a[0]), &(php->a[(php->size) - 1]));
	php->size--;
	HPAdjustDown(php, 0);
}

相信大家一定会有一些问题,因为堆的删除,是删除堆顶元素,大家可能会疑问,为什么不能直接头删。
原因有以下两点:
1.顺序表时间复杂度是O(N),过于复杂。
2.如果头删之后,整个数组是要向前挪一位的,整棵树的结构就全部改变了,父子关系,大小关系全部乱了,需要重新改。

所以我们重新选择一个方法,就是我们将堆顶元素和最后一个元素互换,再尾删,这样可以保证两颗子树从上到下的整个顺序都没有被改变,向下调整就只需要进入一颗子树继续调整就好啦。

5.取堆顶数据

HPDataType HPTop(HP* php)
{
	assert(php);
	assert(php->size > 0);//使用size
	return php->a[0];
}

6.堆的数据个数

int HPSize(HP* php)
{
	assert(php);
	return (php->size);
}

7.堆的判空

bool HPEmpty(HP* php)
{
	assert(php);
	/*if (php->size == 0)
	{
		return true;
	}
	else
	{
		return false;
	}*/
	return (php->size == 0);
}

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

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

相关文章

「Java开发中文指南」IntelliJ IDEA插件安装(一)

IntelliJ IDEA是java编程语言开发的集成环境。IntelliJ在业界被公认为最好的Java开发工具&#xff0c;尤其在智能代码助手、代码自动提示、重构、JavaEE支持、各类版本工具(git、svn等)、JUnit、CVS整合、代码分析、 创新的GUI设计等方面的功能是非常强大的。 插件扩展了Intel…

只考数据结构,计算机评级C+,成都信息工程大学考情分析

成都信息工程大学(C) 考研难度&#xff08;☆☆&#xff09; 内容&#xff1a;23考情概况&#xff08;拟录取和复试分析&#xff09;、院校概况、24专业目录、23复试详情、各专业考情分析、各科目考情分析。 正文1715字&#xff0c;预计阅读&#xff1a;3分钟 2023考情概况 …

【从浅识到熟知Linux】基本指定之cat、more和less

&#x1f388;归属专栏&#xff1a;从浅学到熟知Linux &#x1f697;个人主页&#xff1a;Jammingpro &#x1f41f;每日一句&#xff1a;写完这篇我要去吃晚饭啦&#xff01;&#xff01; 文章前言&#xff1a;本文介绍cat、more和less指令三种查看文件的用法并给出示例和截图…

格式化输入输出

跟着肯哥&#xff08;不是我&#xff09;学格式化输入输出 C语言格式化输入 在C语言中&#xff0c;格式化输入&#xff08;Formatted Input&#xff09;是一种从标准输入读取数据并按照指定格式进行解析的操作&#xff0c;它主要通过使用标准库函数scanf()来实现格式化输入。 …

Go语言的学习笔记2——Go语言源文件的结构布局

用一个只有main函数的go文件来简单说一下Go语言的源文件结构布局&#xff0c;主要分为包名、引入的包和具体函数。下边是main.go示例代码&#xff1a; package mainimport "fmt"func main() { fmt.Println("hello, world") }package main就是表明这个文件…

计算机毕业设计 基于SpringBoot的无人智慧超市管理系统的设计与实现 Java实战项目 附源码+文档+视频讲解+答疑

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

14.docker部署应用的两种企业实践

1.介绍 1.1 说明 这里仅仅说明一下在企业应用的两种简单实践&#xff0c;并不包含自动化这套东西。这里说的两种实践&#xff0c;是我在工作中不同公司使用的两种部署方式&#xff0c;仅供大家参考。 1.2 两种部署方式 第一种&#xff1a;是把环境和app都一起打成一个镜像&…

Javaweb之前端工程化的详细解析

3 前端工程化 3.1 前端工程化介绍 我们目前的前端开发中&#xff0c;当我们需要使用一些资源时&#xff0c;例如&#xff1a;vue.js&#xff0c;和axios.js文件&#xff0c;都是直接再工程中导入的&#xff0c;如下图所示&#xff1a; 但是上述开发模式存在如下问题&#xff…

力扣每日一道系列 --- LeetCode 206. 反转链表

&#x1f4f7; 江池俊&#xff1a; 个人主页 &#x1f525;个人专栏&#xff1a; ✅数据结构探索 ✅LeetCode每日一道 &#x1f305; 有航道的人&#xff0c;再渺小也不会迷途。 LeetCode 206. 反转链表 思路一&#xff1a;头插 初始化两个指针&#xff0c;cur 和 newhead。…

数据结构与算法介绍

什么是数据结构 定义&#xff1a; 数据结构就是研究数据的存储方式&#xff1b;数据存储的目的是方便后期对数据的再利用&#xff1b;选择合适的方式来存储数据&#xff0c;是数据结构的核心内容。 数据存储结构的选择&#xff1a;取决于两方面&#xff0c;即数据的逻辑结构和…

metersphere 设置定时任务和查看报告

设置定时任务 设置时间 查看执行后的测试报告 查看报告详情

【报错栏】(Vue) Invalid handler for event “click“: got undefined

Property or method "add" is not defined on the instance but referenced during render. 翻译&#xff1a; 属性或方法“add”未在实例上定义&#xff0c;但在渲染期间引用。 Invalid handler for event "click": got undefined 翻译&#xff1a; …

使用VUE3实现简单颜色盘,吸管组件,useEyeDropper和<input type=“color“ />的使用

1.使用vueuse中的useEyeDropper来实现滴管的功能和使用input中的type"color"属性来实现颜色盘 效果&#xff1a; 图标触发吸管 input触发颜色盘 组件代码部分 &#xff1a;<dropper> ---- vueuse使用 <template><div class"sRGBHexWrap fbc…

DGL在异构图上的GraphConv模块

回顾同构图GraphConv模块 首先回顾一下同构图中实现GraphConv的主要思路&#xff08;以GraphSAGE为例&#xff09;&#xff1a; 在初始化模块首先是获取源节点和目标节点的输入维度&#xff0c;同时获取输出的特征维度。根据SAGE论文提出的三种聚合操作&#xff0c;需要获取所…

2023亚太杯数学建模B题完整原创论文讲解

大家好呀&#xff0c;从发布赛题一直到现在&#xff0c;总算完成了2023亚太地区数学建模竞赛B题玻璃温室的微气候调控完整的成品论文。 本论文可以保证原创&#xff0c;保证高质量。绝不是随便引用一大堆模型和代码复制粘贴进来完全没有应用糊弄人的垃圾半成品论文。 论文共6…

ZC-OFDM模糊函数原理及仿真

文章目录 前言一、ZC 序列二、ZC-OFDM 信号1、OFDM 信号表达式2、模糊函数表达式三、MATLAB 仿真1、MATLAB 核心源码2、仿真结果①、ZC-OFDM 模糊函数②、ZC-OFDM 距离分辨率③、ZC-OFDM 速度分辨率前言 本文进行 ZC-OFDM 的原理讲解及仿真,首先看一下 ZC-OFDM 的模糊函数仿真…

roseha for windows 11+oracle 11g部署过程

文章目录 一、环境准备关闭防火墙配置hosts共享存储准备 二、部署步骤1.主机A、B安装数据库软件2.主机A进行数据库实例创建3.主机B创建数据库4.安装配置roseha软件 一、环境准备 windows server 2019 oracle 11.2.0.3 EE roseha for windows 11 5个IP地址&#xff1a;2心跳、3…

元宇宙vr线上展馆在线制作降低开发门槛和成本

让人人都拥有自己的元宇宙空间&#xff0c;说起来就是一个令人亢奋的消息&#xff0c;也是大家所期待的&#xff0c;VR元宇宙空间在线编辑平台是VRARAI元宇宙公司深圳华锐视点自主研发的平台&#xff0c;允许用户在虚拟环境中创建、设计和共享空间&#xff0c;操作简单&#xf…

Ubuntu20.04上编译安装TVM

本文主要讲述如何在ubuntu20.04平台上编译TVM代码并在python中import tvm成功。 源代码下载&#xff1a; git clone --recursive https://github.com/apache/tvm tvm 平台环境升级&#xff1a; 1&#xff09; sudo apt-get update 2&#xff09; sudo apt-get install -y pyth…

RK3588平台 USB框架与USB识别流程

一.USB的基本概念 在最初的标准里&#xff0c;USB接头有4条线&#xff1a;电源&#xff0c;D-,D,地线。我们暂且把这样的叫做标准的USB接头吧。后来OTG出现了&#xff0c;又增加了miniUSB接头。而miniUSB接头则有5条线&#xff0c;多了一条ID线,用来标识身份用的。 热插拔&am…