当前位置: 首页 > news >正文

100.【C语言】数据结构之二叉树的堆实现(顺序结构) 1

目录

1.顺序结构

2.示意图

 ​编辑

从物理结构还原为逻辑结构的方法

3.父子节点编号的规律

4.顺序存储的前提条件

5.堆的简介

堆的定义

堆的两个重要性质

小根堆和大根堆 

6.堆的插入

7.堆的实现及操作堆的函数

堆的结构体定义

堆初始化函数HeapInit

堆插入元素函数HeapPush

堆向上调整函数AdjustUp

写法1

写法2

写法3

提问

向上调整的前提

测试堆插入函数


1.顺序结构

存储二叉树的两种结构:一种顺序结构,一种链式结构本文讲顺序结构


2.示意图

 4311a3c884de4d0caec5b45ef6aa9c66.png

上方图中的数字0~6代表各个节点的编号 

逻辑结构:方便人理解的结构 物理结构:实实在在存储的结构

可见顺序结构的底层是用数组(连续)存储的

从物理结构还原为逻辑结构的方法

对于满二叉树而言,

第一层有一个节点,第二层有两个节点,第一层有四个节点......

则可按层拆分

4f110e1b52564653809e45ad5700440e.png

再组合

aac1aff2adc14578a3eb1be99060ba31.png

加上线

68aacacb93554bda9e40b9e6ea2aa5ee.png

 对于完全二叉树而言,做法和上述类似,不再赘述

3.父子节点编号的规律

比如求F的父节点,如果画图则太慢,其实可以看出规律

F编号为5,其父节点C编号为2;E编号为4,其父节点B编号为1;

发现eq?%5B%5Cfrac%7B5-1%7D%7B2%7D%5D%3D2%2C%5B%5Cfrac%7B4-1%7D%7B2%7D%5D%3D%5B1.5%5D%3D1(注:eq?%5Bx%5D为高斯函数,又称向下取整函数)

★★★求父节点b编号的公式:eq?%5B%5Cfrac%7Bchild-1%7D%7B2%7D%5D%3Dfather

在C语言中为father = (child-1)/2;father获得表达式的商

如果给出父节点的编号,求左孩子和右孩子的编号

父节点C编号为2,则左孩子F的编号为2*2+1,则右孩子G的编号为2*2+2

★★★求孩子节点编号的公式:左孩子:eq?2*father+1  右孩子:eq?2*father+2

4.顺序存储的前提条件

结论:完全二叉树(含满二叉树)适合用顺序存储

25f932f64b0c4f89a726508dbdac504f.png

如果非完全二叉树,存储会浪费空间

5.堆的简介

堆的定义

如果有一个关键码的集合eq?K%20%3D%20%5C%7B%20k_0%2Ck_1%2Ck_2%2C...%2Ck_%7Bn-1%7D%5C%7D,把它的所有元素按完全二叉树的顺序存储方式存储在一个一维数组中,并满足:eq?K_i%20%3C%3D%20K_%7B2*i+1%7Deq?K_i%3C%3D%20K_%7B2*i+2%7D%20%28K_i%20%3E%3D%20K_%7B2*i+1%7D%29eq?K_i%20%3E%3D%20K_%7B2*i+2%7D(i=0,1,2,3,..,n)则称为小堆(或大堆)

堆的两个重要性质

  • 堆中某个结点的值总是不大于或不小于其父结点的值;

  • 总是一棵完全二叉树

小根堆和大根堆 

小根堆:树中所有的父节点的值都小于或等于孩子节点的值

大根堆:树中所有的父节点的值都大于或等于孩子节点的值

如果树中所有的父节点的值都等于孩子节点的值,则既为小根堆又为大根堆

注:等定义中并没有规定左孩子和右节点的值的大小关系,因此堆不一定有序

6.堆的插入

由堆的简介可知:堆是一个完全二叉树,因此可以用顺序结构实现

以下方大根堆为例

5516201b19fc4ff4ba832151b1735e7f.jpeg

现要尾插数字20,由存储结构可以看出:空间不够,要扩容

586ea01b4e95478fadf61f4dbb53bc8f.jpeg

插入20前,找其父节点(eq?%5B%5Cfrac%7Bchild-1%7D%7B2%7D%5D%3Dfather),发现后者值为30,可以插入,仍然满足大根堆的性质 

再尾插入60

a761c72718674ece9995f70e1cfc4af1.png

发现不满足大根堆的性质,需要一次调整

4a5e53f5f43649b1a5af1733922837dd.png

发现调整后仍然不满足大根堆的性质(56<60),需要再一次调整 

36899090ed21424586fb62e5227a50d4.png

发现调整后满足大根堆的性质(56<60<70),结束

上述的调整起名为向上调整,最多调整h(二叉树的高度)次

7.堆的实现及操作堆的函数

以大根堆为例

堆的结构体定义

可以用结构体来定义堆,由于堆的底层是用数组存储的,因此三个成员变量:数据域,大小size,容量capacity

写入头文件中

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

堆初始化函数HeapInit

要想使用堆必须先初始化堆(malloc,对size和capacity初始化值)

void HeapInit(HP* php)
{assert(php);php->a = (HPDataType*)malloc(sizeof(HPDataType) * 4);if (php->a == NULL){perror("malloc");return;}php->size = 0;php->capacity = 4;
}

php->capacity跟随malloc函数开辟空间的大小

堆插入元素函数HeapPush

插入前先判断空间是否充足,不够则relloc原来的2倍.之后调用向上调整函数进行插入

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");return;}php->a = tmp;php->capacity *= 2;}php->a[php->size] = x;//插入至数组的最后一个元素的下一个位置(size)php->size++;//数组大小+1//调用向上调整函数AdjustUp(php->a,php->size-1);
}

注意到AdjustUp传的第二个参数是php->size-1

堆向上调整函数AdjustUp

如果a[parent] < a[child],则进行交换,之后调整parent和child的值,以便于下一次调整

写法1

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 (a[parent] < a[child]){Swap(&a[parent], &a[child]);//调整parent和child的值child = parent;parent = (parent - 1) / 2;}
}

写法2

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

写法3

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

提问

已知这几种写法都能成功运行,哪个写法存在不规范的地方?

答:从特殊情况考虑问题,写法2:

当parent==0时,进入循环,若child==1,if判断成立,交换值后,child==0,parent==-1/2==0(取商)

while(parent>=0)条件仍然成立,但不满足if (a[child] > a[parent]),因此break

不规范的地方:child==parent==0就没有必要再次进入循环,建议改成while (child>0)(写法3)

向上调整的前提

除了child位置,前面的数据结构构成堆

测试堆插入函数

main.c手动写入插入一些随机值,以下代码,下断点至return 0;

#include "Heap.h"
int main()
{HP hp;HeapInit(&hp);HeapPush(&hp, 1);HeapPush(&hp, 3);HeapPush(&hp, 0);HeapPush(&hp, 5);HeapPush(&hp, 8);HeapPush(&hp, 12);HeapPush(&hp, 2);HeapPush(&hp, 5);HeapPush(&hp, 30);HeapPush(&hp, 50);return 0;}

打开监视窗口查看

ed16365c491d4a4eb9b111b7b3f5ec30.png

画图后发现符合大根堆的性质

7ab07688e63a4274bcb0527f7b168b07.png

相关文章:

100.【C语言】数据结构之二叉树的堆实现(顺序结构) 1

目录 1.顺序结构 2.示意图 ​编辑 从物理结构还原为逻辑结构的方法 3.父子节点编号的规律 4.顺序存储的前提条件 5.堆的简介 堆的定义 堆的两个重要性质 小根堆和大根堆 6.堆的插入 7.堆的实现及操作堆的函数 堆的结构体定义 堆初始化函数HeapInit 堆插入元素函…...

大模型 VS 大语言模型

最近很多朋友搞不懂大模型和大预言模型的区别&#xff0c;总是把大模型就认为是大语言模型。 今天就用这篇帖子做一个科普。 大模型 概念&#xff1a;大模型是指拥有超大规模参数&#xff08;通常在十亿个以上&#xff09;、复杂计算结构的机器学习模型。它通常能够处理海量数…...

Linux高阶——1117—TCP客户端服务端

目录 1、sock.h socket常用函数 网络初始化函数 首次响应函数 测试IO处理函数 获取时间函数 总代码 2、sock.c SOCKET() ACCEPT()——服务端使用这个函数等待客户端连接 CONNECT()——客户端使用这个函数连接服务端 BIND()——一般只有服务端使用 LISTEN()——服务端…...

【Qt】Qt 在main.cpp中使用tr()函数报错

1. 问题 Qt 在main.cpp中使用tr()报错。 error: tr was not declared in this scope2. 解决方法 main.cpp中注意如下&#xff1a; //添加头文件 #include <QObject>//添加QObject QObject::tr("Hello")3. 参考 Qt tr()函数不起效的小问题...

面向对象高级(5)接口

面向对象高级&#xff08;5&#xff09; 接口 接口就是规范&#xff0c;定义的是一组规则&#xff0c;体现了现实世界中“如果是...则必须能...”的思想。继承是一个"是不是"的is-a关系&#xff0c;而接口实现则是 "能不能"的has-a关系。 1、接口的定义格…...

uniapp发布android上架应用商店权限

先看效果&#xff1a; 实现原理&#xff1a; 一、利用uni.addInterceptor的拦截器&#xff0c;在一些调用系统权限前拦截&#xff0c;进行弹窗展示&#xff0c;监听确定取消实现业务逻辑。 二、弹窗是原生nativeObj进行drawRect绘制的 三、权限申请调用使用的 plus.android.…...

Centos Stream 9安装Jenkins-2.485 构建自动化项目步骤

官网&#xff1a;https://www.jenkins.io/ 1 下载 环境准备&#xff1a; 版本支持查询&#xff1a;https://pkg.jenkins.io/redhat-stable/ 安装JDK17&#xff1a;https://blog.csdn.net/qq_44870331/article/details/140784297 yum -y install epel-release wget upgradew…...

电路模型和电路定理(二)

电路元件 是电路中最基本的组成单元。 电阻元件&#xff1a;表示消耗电能的元件 电感元件&#xff1a;表示产生磁场&#xff0c;储存磁场能的元件 电容元件&#xff1a;表示产生电场&#xff0c;储存电场能量的元件 电压源和电流源&#xff1a;表示将其他形式的能量转变成…...

瑞佑液晶控制芯片RA6807系列介绍 (三)软件代码详解 Part.10(让PNG图片动起来)完结篇

RA6807是RA8876M的缩小版&#xff0c;具备RA8876M的所有功能&#xff0c;只将MCU控制接口进行缩减&#xff0c;仅保留SPI-3和I2C接口&#xff0c;其它功能基本相同。 该芯片最大可控制854x600的分辨率&#xff0c;内建64Mbits显存&#xff0c;多个图层&#xff0c;使用起来相当…...

Qt常用控件 按钮

文章目录 1. QAbstractButton 简介2. QPushButton2.1 例子1&#xff0c;设置按钮的图标2.2 例子2&#xff0c;设置按钮快捷键 3. QRadioButton3.1 介绍3.2 例子1&#xff0c;选择性别3.3 例子2&#xff0c;试试其他的信号3.3 例子3&#xff0c;分组 4. QCheckBox4.1 介绍4.2 例…...

MySQL学习/复习10视图/用户/权限/语言连接数据库

一、视图 1.1创建视图 1.2视图影响基表 1.3基表影响视图 1.4删除视图 1.5视图使用规则 二、数据库的用户 2.1mysql中的user表 注意事项&#xff1a;主机/用户名/密码/权限 2.2用户的创建 注意事项&#xff1a;设置密码与登录地点需谨慎 2.3删除用户 注意事项&#xff1a;% 2.4…...

vulfocus在线靶场:tomcat-pass-getshell 弱口令 速通手册

目录 一、启动环境&#xff0c;访问页面&#xff0c;并登录&#xff0c;账号密码都是tomcat 二、哥斯拉打war包&#xff0c;图解 三、上传war包&#xff0c;图解 四、访问我们直接url/木马文件名/木马文件.jsp&#xff0c;是否存在了 五、 哥斯拉测试连接结果success&…...

c#:winform调用bartender实现打印(学习整理笔记)

效果 学习路径 C# winform调用Bartender进行自定义打印、批量打印、检索文件夹中的模板_哔哩哔哩_bilibili 一、初始环境搭建见&#xff1a; c#:winform引入bartender-CSDN博客https://blog.csdn.net/weixin_46001736/article/details/143989473?sharetypeblogdetail&s…...

牛客题库 21738 牛牛与数组

牛牛与数组题目链接 题目大意 牛牛喜欢这样的数组: 1:长度为n 2:每一个数都在1到k之间 3:对于任意连续的两个数A,B,A<=B 与(A % B != 0) 两个条件至少成立一个请问一共有多少满足条件的数组,对 1 e 9 + 7 1e^9+7 1e9+7 取模 输入格式 输入两个整数 n , k n,k n,…...

探索PDFMiner:Python中的PDF解析利器

文章目录 **探索PDFMiner&#xff1a;Python中的PDF解析利器**1. 背景介绍&#xff1a;为何选择PDFMiner&#xff1f;2. PDFMiner是什么&#xff1f;3. 如何安装PDFMiner&#xff1f;4. 简单库函数使用方法4.1 提取文本4.2 获取页面布局信息4.3 提取表格数据4.4 提取图像 5. 应…...

掌握Go语言中的异常控制:panic、recover和defer的深度解析

掌握Go语言中的异常控制:panic、recover和defer的深度解析 在Go语言的编程世界中,异常处理是一个不可忽视的话题。Go语言提供了panic、recover和defer三个关键字来处理程序中的异常情况。本文将深入探讨这三个关键字的工作原理、使用场景和最佳实践,帮助读者在实际编程中更…...

云讷科技Kerloud无人飞车专利发布

云讷科技Kerloud无人飞车获得了“一种室内外两用的四旋翼无人飞车”的实用新型专利证书&#xff0c;作为科教社区第一款四旋翼飞车&#xff0c;这项技术结合了无人机和无人车的优势&#xff0c;提供了一种能够在多种环境下使用的多功能飞行器。 这项设计的优势如下&#xff…...

企业信息化-走进身份管理之搭建篇

​一、身份管理是什么 我们先要弄懂统一身份管理到底是什么&#xff1f; 统一身份管理&#xff08;Unified Identity Manager&#xff0c;UIM&#xff09;&#xff0c;身份管理&#xff08;Identity Management&#xff0c;简称IDM&#xff09;&#xff0c;也被称为IAM&#…...

实践指南:EdgeOne与HAI的梦幻联动

在当今快速发展的数字时代&#xff0c;安全和速度已成为网络服务的基石。EdgeOne&#xff0c;作为腾讯云提供的边缘安全加速平台&#xff0c;以其全球部署的节点和强大的安全防护功能&#xff0c;为用户提供了稳定而高效的网络体验。而HAI&#xff08;HyperApplicationInventor…...

Exploring Prompt Engineering: A Systematic Review with SWOT Analysis

文章目录 题目摘要简介方法论背景相关工作评估结论 题目 探索快速工程&#xff1a;基于 SWOT 分析的系统评价 论文地址&#xff1a; https://arxiv.org/abs/2410.12843 摘要 在本文中&#xff0c;我们对大型语言模型 (LLM) 领域的提示工程技术进行了全面的 SWOT 分析。我们强…...

无机布防火卷帘门价格怎么算?按尺寸定制,按需报价

无机布防火卷帘门作为建筑防火分区的核心设备&#xff0c;价格一直是工程采购的关注重点。很多用户在询价时&#xff0c;会发现不同厂家的报价差异较大&#xff0c;这是因为无机布防火卷帘门的价格并非按统一单价计算&#xff0c;而是完全根据项目的实际需求定制化核算。 &…...

ComfyUI-Manager终极指南:3个核心功能彻底解决AI工作流管理难题

ComfyUI-Manager终极指南&#xff1a;3个核心功能彻底解决AI工作流管理难题 【免费下载链接】ComfyUI-Manager ComfyUI-Manager is an extension designed to enhance the usability of ComfyUI. It offers management functions to install, remove, disable, and enable vari…...

别再手动改路径了!用LabVIEW + MATLAB Script做自动化测试,这份环境配置指南让你效率翻倍

LabVIEW与MATLAB深度整合&#xff1a;构建自动化测试系统的工程实践指南在工业自动化与测试测量领域&#xff0c;LabVIEW和MATLAB的组合堪称黄金搭档。LabVIEW擅长硬件接口和实时控制&#xff0c;而MATLAB在算法开发和数据分析方面具有无可比拟的优势。本文将深入探讨如何将两者…...

Python PIL 画矩形框

基础代码 from PIL import Image, ImageDraw# 打开图片 img Image.open(your_image.jpg)# 创建绘图对象 draw ImageDraw.Draw(img)# 矩形坐标 (x1, y1, x2, y2) coords (23, 21, 69, 76)# 画矩形框&#xff08;红色&#xff0c;线宽2&#xff09; draw.rectangle(coords, ou…...

ComfyUI-Manager完整指南:如何轻松管理你的AI工作流扩展库

ComfyUI-Manager完整指南&#xff1a;如何轻松管理你的AI工作流扩展库 【免费下载链接】ComfyUI-Manager ComfyUI-Manager is an extension designed to enhance the usability of ComfyUI. It offers management functions to install, remove, disable, and enable various c…...

Windows开机自动全屏打开指定网页?一个快捷方式参数就搞定(Chrome/Edge/Firefox教程)

Windows开机自动全屏展示网页的终极方案每次开机都要手动打开浏览器、输入网址、切换全屏模式&#xff1f;这种重复操作不仅浪费时间&#xff0c;还容易在重要演示时手忙脚乱。想象一下&#xff1a;电脑启动后自动全屏显示你的仪表盘、会议日程或是监控大屏&#xff0c;整个过程…...

【2026实测】怎么提高论文原创度?盘点8款主流降AI工具,附结构级优化指南

写文章最怕碰到什么&#xff0c;是辛辛苦苦自己码出来的字&#xff0c;却被标了极高的AI值。目前很多文本审核机制对内容的原创度要求极高&#xff0c;纯手写的初稿也可能因为句式太工整被判定为机器生成的。 为了帮几个快被这事折腾疯了的学弟学妹找条出路&#xff0c;我花了…...

为什么你的霓虹总像“塑料灯带”?Midjourney光子散射模拟缺陷曝光:3个被官方隐瞒的--sref调参禁区

更多请点击&#xff1a; https://kaifayun.com 第一章&#xff1a;为什么你的霓虹总像“塑料灯带”&#xff1f; 霓虹效果在现代 UI 设计中无处不在——按钮悬停、加载指示器、焦点高亮……但多数实现却流于表面&#xff1a;生硬的 box-shadow、固定色值的渐变边框、缺乏物理感…...

终极Obsidian笔记模板指南:如何用kepano-obsidian构建你的第二大脑

终极Obsidian笔记模板指南&#xff1a;如何用kepano-obsidian构建你的第二大脑 【免费下载链接】kepano-obsidian My personal Obsidian vault template. A bottom-up approach to note-taking and organizing things I am interested in. 项目地址: https://gitcode.com/gh_…...

C语言有符号和无符号在内存中的存储方式区别小结

在 C 语言中&#xff0c;​有符号类型&#xff08;如 signed char、signed int&#xff09;和无符号类型&#xff08;如 unsigned char、unsigned int&#xff09;在内存中的存储方式本质上没有区别——它们都是以二进制位的形式存储数值的。两者的核心差异体现在对二进制位的解…...