【数据结构】C++语言实现二叉树的介绍及堆的实现(详细解读)

9efbcbc3d25747719da38c01b3fa9b4f.gif

 c语言中的小小白-CSDN博客c语言中的小小白关注算法,c++,c语言,贪心算法,链表,mysql,动态规划,后端,线性回归,数据结构,排序算法领域.https://blog.csdn.net/bhbcdxb123?spm=1001.2014.3001.5343

给大家分享一句我很喜欢我话:

知不足而奋进,望远山而前行!!!

铁铁们,成功的路上必然是孤独且艰难的,但是我们不可以放弃,远山就在前方,但我们能力仍然不足,所有我们更要奋进前行!!!

今天我们更新了二叉树内容,

🎉 欢迎大家关注🔍点赞👍收藏⭐️留言📝

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

  • 有一个特殊的结点,称为根结点,根节点没有前驱结点。
  • 除跟根结点外,其余结点被分成M(M>0)个互不相交的集合T1、T2…Tm,其中每一个集合Ti(1<=i<=m)又是一棵结构与树类似的子树。每颗子树的根节点有且只有一个前驱,可以有0个或多个后继。
  • 因此,树是递归定义的。

有关树的一些概念:

  1. 节点的度:一个节点含有的子树的个数称为该节点的度;如上图:A的为6
  2. 叶节点或终端节点:度为0的节点称为叶节点;如上图:B、C、H、I…等节点为叶节点非终端节点或分支节点:度不为0的节点;如上图:D、E、F、G…等节点为分支节点
  3. 兄弟节点:具有相同父节点的节点互称为兄弟节点;如上图:B、C是兄弟节点
  4. 树的度:一棵树中,最大的节点的度称为树的度;如上图:树的度为6
  5. 节点的层次:从根开始定义起,根为第1层,根的子节点为第2层,以此类推;
  6. 树的高度或深度:树中节点的最大层次;如上图:树的高度为4(有两种说法-从0开始还是从1开始,空树-1,空树0)
  7. 节点的祖先:从根到该节点所经分支上的所有节点;如上图:A是所有节点的祖先
  8. 子孙:以某节点为根的子树中任一节点都称为该节点的子孙。如上图:所有节点都是A的子孙
  9. 森林:由m (m>0)棵互不相交的多颗树的集合称为森林;(数据结构中的学习并查集本质就是一个森林)——(日常很少碰到森林,并查集就是一个森林)

其中这些概念中第 4、6、7条较为重要,其余了解一下即可。

树的要求:

  • 子树是不相交的
  • 除了根结点之外,每个结点有且仅有一个父结点
  • 一个N个结点的树有N-1条边

树的表示

相对于线性表,树的结构就复杂很多了。最常用的表示方法——孩子兄弟表示法。

二叉树

与普通的树最大的不同是它最多只有两个子树。

特殊的二叉树

  1. 满二叉树:每一层都是满的。

    假设一棵满二叉树的高度是 h,那么它的总结点个数是:20+21+22+…2(h-1) =N。

    推导公式:2^h-1 = N;h = log2N+1以2位底N的对数+1。

  2. 完全二叉树

完全二叉树是个效率很高的数据结构,完全二叉树是由满二叉树引出来的。

假设树的高度是h,前h-1层是满的,最后一层不满,但是最后一层从左往右都是连续的。

最后一层最少有一个结点。

结点个数为:2^h-1-X= N,高度近似为:h = log2N+1+X以二为底N的对数+1

图有点难看不要介意

这些就是关于树的一些基本概念,下面我们来介绍一下关于树的实现。

堆的实现:

这里我们将会分为初始化、销毁、建堆、堆的删除、取出堆顶元素、判断是否为空、向上调整和向下调整这几步来完成。

头文件及堆结构的定义:

#pragma once
#include<stdio.h>
#include<iostream>
#include<stdlib.h>
#include<assert.h>
#include<algorithm>
#include<cmath>
#include<utility>typedef int HPDataType;typedef struct Heap
{HPDataType* a;int size;int capacity;
}HP;

初始化:

//初始化
void HPInit(HP* php)
{assert(php);php->a = NULL;php->capacity = php->size= 0;}

销毁:

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

向上调整:

//向上调整(小根堆)
void AdjustUp(HPDataType* a, int child)
{int parent = (child - 1) / 2;while (child>0){if (a[child] < a[parent])//小于就换就相当于建小堆//if (a[child] > a[parent])//大于就换就会变成大堆{std::swap(a[child], a[parent]);child = parent;parent = (child - 1) / 2;}else{break;}}
}

建堆:

void HPPush(HP* php, HPDataType x)
{assert(php);if (php->size == php->capacity){int newcapacity = php->capacity == 0 ? 4 : php->capacity * 2;HPDataType* tmp = (HPDataType*)realloc(php->a,sizeof(HPDataType) * newcapacity);if (tmp == NULL){perror("realloc failed!!!");return;}php->a = tmp;php->capacity = newcapacity;}php->a[php->size++] = x;//向上调整AdjustUp(php->a, php->size - 1);
}

向下调整:

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{++child;}if (a[child] < a[parent]){std::swap(a[child], a[parent]);parent = child;child = parent * 2 + 1;}else break;}}

删除堆顶的数据:

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

判空:

bool HPEmpty(HP* php)
{assert(php);return php->size == 0;
}

总代码:

TEST.c:

#include"Heap.h"void TestHeap1()
{int a[] = { 4,2,8,1,5,6,7,9 };HP hp;HPInit(&hp);for (size_t i = 0; i < sizeof(a) / sizeof(int); i++){HPPush(&hp, a[i]);}while (!HPEmpty(&hp)){printf("%d ", HPTop(&hp));HPPop(&hp);}HPDestroy(&hp);
}void HeapSort(int* a, int n)
{//首先建堆//升序:建大堆//降序:建小堆for (int i=0;i<n;i++){AdjustUp(a, i);}int end = n - 1;///这里>0即可,因为=0时只剩下最后一个,就不再需要继续进行了while (end>0)//思路就是:比如我们升序排序,那么我们就利用大根堆,每次都将最大的那个数放在最顶上,然后将它和最后一个交换,然后让整体的大小--,那么最后一个就不再会受影响{std::swap(a[0], a[end]);AdjustDown(a, end, 0);--end;}}void TestHeap2()
{int a[] = { 4,2,8,1,5,6,9,7,3,10,23,14,125 };HeapSort(a, sizeof(a) / sizeof(0));for (int i = 0; i < sizeof(a) / sizeof(a[0]); i++){std::cout << a[i] << " ";}
}int main()
{TestHeap2();return 0;
}

Heap.c:

#include"Heap.h"//初始化
void HPInit(HP* php)
{assert(php);php->a = NULL;php->capacity = php->size= 0;}//销毁
void HPDestroy(HP* php)
{assert(php);free(php);php->a = NULL;php->capacity = php->size = 0;}//向上调整(小根堆)
void AdjustUp(HPDataType* a, int child)
{int parent = (child - 1) / 2;while (child>0){if (a[child] < a[parent])//小于就换就相当于建小堆//if (a[child] > a[parent])//大于就换就会变成大堆{std::swap(a[child], a[parent]);child = parent;parent = (child - 1) / 2;}else{break;}}
}//建堆
void HPPush(HP* php, HPDataType x)
{assert(php);if (php->size == php->capacity){int newcapacity = php->capacity == 0 ? 4 : php->capacity * 2;HPDataType* tmp = (HPDataType*)realloc(php->a,sizeof(HPDataType) * newcapacity);if (tmp == NULL){perror("realloc failed!!!");return;}php->a = tmp;php->capacity = newcapacity;}php->a[php->size++] = x;//向上调整AdjustUp(php->a, php->size - 1);
}//向下调整
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{++child;}if (a[child] < a[parent]){std::swap(a[child], a[parent]);parent = child;child = parent * 2 + 1;}else break;}}//删除堆顶的数据
void HPPop(HP* php)
{assert(php);assert(php->size > 0);std::swap(php->a[0], php->a[php->size - 1]);//就是将第一个与最后一个换掉,然后将他们向下调整,php->size--;//直接size--删去最后一个元素AdjustDown(php->a, php->size, 0);
}//取出堆顶数据
HPDataType HPTop(HP* php)
{assert(php);assert(php->size > 0);return php->a[0];
}bool HPEmpty(HP* php)
{assert(php);return php->size == 0;
}

Heap.h:

#pragma once
#include<stdio.h>
#include<iostream>
#include<stdlib.h>
#include<assert.h>
#include<algorithm>
#include<cmath>
#include<utility>typedef int HPDataType;typedef struct Heap
{HPDataType* a;int size;int capacity;
}HP;//初始化
void HPInit(HP* php);//销毁
void HPDestroy(HP* php);//建堆
void HPPush(HP* php,HPDataType x);//堆的删除
void HPPop(HP* php);//取出堆顶数据
HPDataType HPTop(HP* php);bool HPEmpty(HP* php);void AdjustUp(HPDataType* a, int child);
void AdjustDown(HPDataType* a, int n, int parent);

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

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

相关文章

分布式系统的一致性与共识算法(三)

顺序一致性(Sequential Consistency) ZooKeeper 一种说法是ZooKeeper是最终一致性&#xff0c;因为由于多副本、以及保证大多数成功的ZAB协议&#xff0c;当一个客户端进程写入一个新值&#xff0c;另外一个客户端进程不能保证马上就能读到这个值&#xff0c;但是能保证最终能…

【车载开发系列】SID$11服务配置

【车载开发系列】SID$11服务配置 前言 ECUReset(ECU重置),ECU作为Server端,执行Client发送来ECU Reset请求中重启的类型(通过子服务区分)。对于UDS协议关于处理该请求的逻辑,没有强制性定义。 Step1:SID和SubFunction的追加 BasicEditor→Dcm→DcmConfigSet→DcmDs…

vs2019 c++里用 typeid() . name () 与 typeid() . raw_name () 测试数据类型的区别

&#xff08;1&#xff09; 都知道&#xff0c;在 vs2019 里用 typeid 打印的类型不大准&#xff0c;会主动去掉一些修饰符&#xff0c; const 和引用 修饰符会被去掉。但也可以给咱们验证学到的代码知识提供一些参考。那么今天发现其还有 raw_name 成员函数&#xff0c;这个函…

AES分组密码

一、AES明文和密钥位数 RIJNDAEL 算法数据块长度和密钥长度都可独立地选定为大于等于 128 位且小于等于 256 位的 32 位的任意倍数。 而美国颁布 AES 时却规定数据块的长度为 128 位、密钥的长度可分别选择为 128 位&#xff0c; 192 位或 256 位 1.1 状态 中间结果叫做状态…

建模:3dmax

3Dmax 制作模型和动画&#xff08;橘肉&#xff09;&#xff1b; RizomUV 对模型进行展UV&#xff08;橘皮&#xff09;&#xff1b; Substance Painter 纹理手绘&#xff08;给橘皮制定想要的皮肤&#xff09;&#xff1b; 1.基础 1.1可编辑多边形、可编辑样条线 体、面都需要…

Polylang Pro插件下载:多语言网站构建的终极解决方案

在全球化的今天&#xff0c;多语言网站已成为企业拓展国际市场的重要工具。然而&#xff0c;创建和管理一个多语言网站并非易事。幸运的是&#xff0c;Polylang Pro插件的出现&#xff0c;为WordPress用户提供了一个强大的多语言解决方案。本文将深入探讨Polylang Pro插件的功能…

暴力数据结构之二叉树(堆的相关知识)

1. 堆的基本了解 堆&#xff08;heap&#xff09;是计算机科学中一种特殊的数据结构&#xff0c;通常被视为一个完全二叉树&#xff0c;并且可以用数组来存储。堆的主要应用是在一组变化频繁&#xff08;增删查改的频率较高&#xff09;的数据集中查找最值。堆分为大根堆和小根…

什么是最大路径?什么是极大路径?

最近学习中&#xff0c;在这两个概念上出现了混淆&#xff0c;导致了一些误解&#xff0c;在此厘清。 最大路径 在一个简单图G中&#xff0c;u、v之间的距离 d ( u , v ) min ⁡ { u 到 v 的最短路的长度 } d(u,v) \min \{ u到v的最短路的长度 \} d(u,v)min{u到v的最短路的…

wefaf

c语言中的小小白-CSDN博客c语言中的小小白关注算法,c,c语言,贪心算法,链表,mysql,动态规划,后端,线性回归,数据结构,排序算法领域.https://blog.csdn.net/bhbcdxb123?spm1001.2014.3001.5343 给大家分享一句我很喜欢我话&#xff1a; 知不足而奋进&#xff0c;望远山而前行&am…

每天Get一个小技巧:用DolphinScheduler实现隔几天调度

转载自tuoluzhe8521 这篇小短文将教会你如何使用Apache DolphinScheduler实现隔几天调度&#xff0c;有此需求的小伙伴学起来&#xff01; 1 场景分析 DolphinScheduler定时器模块-定时调度时每3秒|每3分钟|每3天这种定时&#xff0c;不能够跨分钟&#xff0c;跨小时&#x…

【C++】:string类的基本使用

目录 引言一&#xff0c;string类对象的常见构造二&#xff0c;string类对象的容量操作三&#xff0c;string类对象的访问及遍历操作四&#xff0c;string类对象的修改操作五&#xff0c;string类非成员函数六&#xff0c;整形与字符串的转换 引言 string 就是我们常说的"…

如何对SQL Server中的敏感数据进行加密解密?

为什么需要对敏感数据进行加密&#xff1f; 近几年有不少关于个人数据泄露的新闻&#xff08;个人数据通常包含如姓名、地址、身份证号码、财务信息等&#xff09;&#xff0c;给事发公司和被泄露人都带来了不小的影响。 许多国家和地区都出台了个人数据保护的法律法规&#…

Unity Animation--动画窗口指南(使用动画视图)

Unity Animation--动画窗口指南&#xff08;使用动画视图&#xff09; 使用动画视图 window -> Animation 即可打开窗口 查看GameObject上的动画 window -> Animation -> Animation 默认快捷键 Ctrl 6 动画属性列表 在下面的图像中&#xff0c;“动画”视图&am…

思科模拟器--2.静态路由和默认路由配置24.5.15

首先&#xff0c;创建三个路由器和两个个人电脑。 接着&#xff0c;配置两台电脑的IP&#xff0c;子网掩码和默认网关 对Router 0&#xff0c;进行以下命令&#xff1a; 对Router进行以下命令&#xff1a; 对Router2进行以下命令&#xff1a; 本实验完成。 验证&#xff1a;PC…

Vue3+ts(day06:路由)

学习源码可以看我的个人前端学习笔记 (github.com):qdxzw/frontlearningNotes 觉得有帮助的同学&#xff0c;可以点心心支持一下哈&#xff08;笔记是根据b站上学习的尚硅谷的前端视频【张天禹老师】&#xff0c;记录一下学习笔记&#xff0c;用于自己复盘&#xff0c;有需要学…

【ARMv8/v9 系统寄存器 5 -- ARMv8 Cache 控制寄存器 SCTRL_EL1 使用详细介绍】

关于ARM Cache 详细学习推荐专栏&#xff1a; 【ARM Cache 专栏】 【ARM ACE Bus 与 Cache 专栏】 文章目录 ARMv8/v9 Cache 设置寄存器ARMv8 指令 Cache 使能函数测试代码 ARMv8/v9 Cache 设置寄存器 关于寄存器SCTRL_EL1 的详细介绍见文章&#xff1a;【ARMv8/v9 异常模型入…

西南大学计算机考研,选学硕还是专硕?西南大学计算机考研考情分析!

西南大学&#xff08;Southwest University&#xff09;是教育部直属&#xff0c;教育部、农业农村部、重庆市共建的重点综合大学&#xff0c;是国家首批"双一流"建设高校&#xff0c;"211工程"和"985工程优势学科创新平台"建设高校。现任党委书…

【嵌入式大赛应用赛道】机械手臂

电机 进步电机&#xff1a;它的转动是以确定的步数进行的&#xff0c;只要计算好脉冲数量和频率&#xff0c;就可以准确预测和控制电机的转动角度、速度以及停止的位置 伺服电机&#xff1a;将输入的电信号&#xff08;如电压或电流指令&#xff09;转换成轴上的精确旋转运动…

大模型算法(一):从Transformer到ViT再到LLaMA

单任务/单领域模型 深度学习最早的研究集中在针对单个领域或者单个任务设计相应的模型。 对于CV计算机视觉领域&#xff0c;最常用的模型是CNN卷积模型。其中针对计算机视觉中的不同具体任务例如分类任务&#xff0c;目标检测任务&#xff0c;图像分割任务&#xff0c;以CNN作…

【传知代码】VRT: 关于视频修复的模型(论文复现)

前言&#xff1a;随着数字媒体技术的普及&#xff0c;制作和传播视频内容变得日益普遍。但是&#xff0c;视频中由于多种因素&#xff0c;例如传输、存储和录制设备等&#xff0c;经常出现质量上的问题&#xff0c;如图像模糊、噪声干扰和低清晰度等。这类问题对用户的体验和观…