当前位置: 首页 > 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 分析。我们强…...

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站&#xff0c;会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后&#xff0c;网站没有变化的情况。 不熟悉siteground主机的新手&#xff0c;遇到这个问题&#xff0c;就很抓狂&#xff0c;明明是哪都没操作错误&#x…...

docker详细操作--未完待续

docker介绍 docker官网: Docker&#xff1a;加速容器应用程序开发 harbor官网&#xff1a;Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台&#xff0c;用于将应用程序及其依赖项&#xff08;如库、运行时环…...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器

一.自适应梯度算法Adagrad概述 Adagrad&#xff08;Adaptive Gradient Algorithm&#xff09;是一种自适应学习率的优化算法&#xff0c;由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率&#xff0c;适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...

mongodb源码分析session执行handleRequest命令find过程

mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程&#xff0c;并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令&#xff0c;把数据流转换成Message&#xff0c;状态转变流程是&#xff1a;State::Created 》 St…...

如何理解 IP 数据报中的 TTL?

目录 前言理解 前言 面试灵魂一问&#xff1a;说说对 IP 数据报中 TTL 的理解&#xff1f;我们都知道&#xff0c;IP 数据报由首部和数据两部分组成&#xff0c;首部又分为两部分&#xff1a;固定部分和可变部分&#xff0c;共占 20 字节&#xff0c;而即将讨论的 TTL 就位于首…...

如何在网页里填写 PDF 表格?

有时候&#xff0c;你可能希望用户能在你的网站上填写 PDF 表单。然而&#xff0c;这件事并不简单&#xff0c;因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件&#xff0c;但原生并不支持编辑或填写它们。更糟的是&#xff0c;如果你想收集表单数据&#xff…...

如何更改默认 Crontab 编辑器 ?

在 Linux 领域中&#xff0c;crontab 是您可能经常遇到的一个术语。这个实用程序在类 unix 操作系统上可用&#xff0c;用于调度在预定义时间和间隔自动执行的任务。这对管理员和高级用户非常有益&#xff0c;允许他们自动执行各种系统任务。 编辑 Crontab 文件通常使用文本编…...

C语言中提供的第三方库之哈希表实现

一. 简介 前面一篇文章简单学习了C语言中第三方库&#xff08;uthash库&#xff09;提供对哈希表的操作&#xff0c;文章如下&#xff1a; C语言中提供的第三方库uthash常用接口-CSDN博客 本文简单学习一下第三方库 uthash库对哈希表的操作。 二. uthash库哈希表操作示例 u…...

android RelativeLayout布局

<?xml version"1.0" encoding"utf-8"?> <RelativeLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"android:layout_height"match_parent"android:gravity&…...

消息队列系统设计与实践全解析

文章目录 &#x1f680; 消息队列系统设计与实践全解析&#x1f50d; 一、消息队列选型1.1 业务场景匹配矩阵1.2 吞吐量/延迟/可靠性权衡&#x1f4a1; 权衡决策框架 1.3 运维复杂度评估&#x1f527; 运维成本降低策略 &#x1f3d7;️ 二、典型架构设计2.1 分布式事务最终一致…...