IT公司的吉祥“树” 二叉树-(堆)C语言创建(一)

简介: IT公司的吉祥“树” 二叉树-(堆)C语言创建

🍪前言


       🍁经过前面的学习,我们了解了一定的数据结构的知识,栈以及队列的强大我们也有所见证,见识到了链表的速度,以及带头双链表的便捷,也有几了道在线OJ的刷题经验了。


       🍁这段时间的自我提升,也能接受传说中的二叉树了,下面我将带领大家认识一下什么是二叉树以及二叉树的基本概念,学习二叉树中的堆的结构,后面也会学习堆的牛逼之处堆排序,这可是比冒泡排序更快更方便的一种排序方法(后面我会继续更新的,有想了解的可以关注一下,也会有堆相关的OJ题目讲解)


一、树概念及结构    


✅基本概念


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


🥝有一个特殊的结点,称为根结点,根节点没有前驱结点


🥝除根节点外,其余结点被分成M(M>0)个互不相交的集合T1、T2、…...、Tm,其中每一个集合Ti(1<= i <= m)又是一棵结构与树类似的子树。每棵子树的根结点有且只有一个前驱,可以有0个或多个后继。


🥝因此,树是递归定义的。


🚨注意:树形结构中,子树之间不能有交集,否则就不是树形结构。


       🚩下面这些就是个别比较典型的非树结构


cf81c1827226c275b37fff1821f53265_afd3cd21e3e046f09dd16901697ed035.png


✅树的专有名词


       🍟了解完基本树的结构,下面还有一碟开胃小菜,请各位客官细品🥰


       🍁下面介绍了一些树中的一些专有名词,以下面这个图中的树为例


image.png


⭕节点的度:一个节点含有的子树的个数称为该节点的度; 如上图:A的为6


⭕叶节点或终端节点:度为0的节点称为叶节点; 如上图:B、C、H、I...等节点为叶节点


⭕非终端节点或分支节点:度不为0的节点; 如上图:D、E、F、G...等节点为分支节点


⭕父节点:若一个节点含有子节点,则这个节点称为其子节点的父节点; 如上图:A是B的父节点


⭕孩子节点:一个节点含有的子树的根节点称为该节点的子节点; 如上图:B是A的孩子节点


⭕兄弟节点:具有相同父节点的节点互称为兄弟节点; 如上图:B、C是兄弟节点


⭕树的度:一棵树中,最大的节点的度称为树的度; 如上图:树的度为6


⭕节点的层次:从根开始定义起,根为第1层,根的子节点为第2层,以此类推


⭕树的高度或深度:树中节点的最大层次; 如上图:树的高度为4


⭕堂兄弟节点:双亲在同一层的节点互为堂兄弟;如上图:H、I互为兄弟节点


⭕节点的祖先:从根到该节点所经分支上的所有节点;如上图:A是所有节点的祖先


⭕子孙:以某节点为根的子树中任一节点都称为该节点的子孙。如上图:所有节点都是A的子孙


⭕森林:由m(m>0)棵互不相交的树的集合称为森林


✅ 树的表示


       树结构相对线性表就比较复杂了,要存储表示起来就比较麻烦了,既然保存值域,也要保存结点和结点之间的关系,实际中树有很多种表示方式如:双亲表示法,孩子表示法、孩子双亲表示法以及孩子兄弟表示法等。


       🍁我们这里就简单的了解其中最常用的孩子兄弟表示法。🥰


🚩孩子兄弟表示法


       🍎孩子兄弟表示法,顾名思义是只有孩子和兄弟的表示方法,即:父亲的 child 地址只存最左边的那个孩子,孩子的兄弟地址记录了他的兄弟(举个例子就是:在家里父亲要找你们兄妹几个去吃饭,父亲只需要找到长子,然后让长子去找他的兄弟姐妹们)


       🍎我们还是老套路拿图来解释:

47ea3c60c716906146e0dd2dafd6e4cc_a94e06a36715497eb74f2754965d43c3.png

        下面就是代码实现的过程了


typedef int DataType;
struct Node
{
    struct Node* _firstChild1;     // 第一个孩子结点
    struct Node* _pNextBrother;    // 指向其下一个兄弟结点
    DataType _data;                // 结点中的数据域
};


二、二叉树概念及结构


       ✅概念


      🍟 一棵二叉树是结点的一个有限集合,该集合由一个根节点加上两棵别称为左子树和右子树的二叉树组成(或者为空)。


a6b909c9a4939643c2aac201d3c24db3_7ef47d6543e5457eabc2603d0129ead3.png


从上图可以看出:


⭕二叉树不存在度大于2的结点

⭕二叉树的子树有左右之分,次序不能颠倒,因此二叉树是有序树


🚨注意:对于任意的二叉树都是由以下几种情况复合而成的


e3e9afd25fc356451340a6936a825789_319434e0d13a4d67a9f49c48eb1bdde9.png


😍😍现实中的二叉树(又称IT公司的吉祥物)😍😍


486c866242ec9b738c0e75dbb91f322a_34f8f0ff785a41e9b9bc8258585b1614.jpeg

2ae3368629d13bab6606fda50f10ce32_0b1908bd968aee3374dcd7bf3ffaf314.jpeg


        😍😍同学们看到这两张图会不会有很神圣的感觉,我会感觉神圣的感觉。😍😍


而且这些“树”肯定能做IT公司的吉祥物!!!😍😍😍   (泰裤辣!!!)


✅特殊的二叉树


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


⭕完全二叉树:完全二叉树是效率很高的数据结构,完全二叉树是由满二叉树而引出来的。对于深度为K的,有n个结点的二叉树,当且仅当其每一个结点都与深度为K的满二叉树中编号从1至n的结点一一对应时称之为完全二叉树。 要注意的是满二叉树是一种特殊的完全二叉树。

🚨注意:满二叉树也属于特殊的完全二叉树!!!


eeba38fbdb70ac9aed3d747706f51166_055b3b0690c443ee910e9d19126672e2.png


二叉树的性质


⭕若规定根节点的层数为1,则一棵非空二叉树的第i层上最多有 2^(i-1)个结点.


⭕若规定根节点的层数为1,则深度为 h 的二叉树的最大结点数是 2^h-1.


⭕对任何一棵二叉树, 如果度为0其叶结点个数为n。 , 度为2的分支结点个数为n2 ,则有n。=n2+1


⭕若规定根节点的层数为1,具有n个结点的满二叉树的深度,h= log2(n+1). (ps:log2(n+1) 是log以2为底,n+1为对数)


⭕对于具有 n 个结点的完全二叉树,如果按照从上至下从左至右的数组顺序对所有节点从0开始编号,则对于序号为 i 的结点有:


若i>0,i位置节点的双亲序号:(i-1)/2;i=0,i 为根节点编号,无双亲节点

若2i+1<n,左孩子序号:2i+1,2i+1>=n 否则无左孩子

若2i+2<n,右孩子序号:2i+2,2i+2>=n 否则无右孩子


✅二叉树的存储结构

 

🍪二叉树一般可以使用两种结构存储,一种顺序结构,一种链式结构。


🍁顺序存储


       🥝 顺序结构存储就是使用数组来存储,一般使用数组只适合表示完全二叉树,因为不是完全二叉树会有空间的浪费。而现实中使用中只有堆才会使用数组来存储,关于堆我们后面会专门讲解。二叉树顺序存储在物理上是一个数组,在逻辑上是一颗二叉树。


cc0754819527487b33edf866fb876ac4_13095874e84a4d80857562493d46defe.png


🍁链式存储


       🥝 二叉树的链式存储结构是指,用链表来表示一棵二叉树,即用链来指示元素的逻辑关系。 通常的方法是链表中每个结点由三个域组成,数据域和左右指针域,左右指针分别用来给出该结点左孩子和右孩子所在的链结点的存储地址 。链式结构又分为二叉链和三叉链,当前我们学习中一般都是二叉链,后面会学到高阶数据结构如红黑树等会用到三叉链.


ddadcf40ea1043f93a574118dfa56a61_d31152f5fb207afded7c286e26528081.jpeg


        🍔链式存储结构的代码来一份吧!!!


typedef int BTDataType;
// 二叉链
struct BinaryTreeNode
{
    struct BinTreeNode* _pLeft; // 指向当前节点左孩子
    struct BinTreeNode* _pRight; // 指向当前节点右孩子
    BTDataType _data; // 当前节点值域
}
// 三叉链
struct BinaryTreeNode
{
    struct BinTreeNode* _pParent; // 指向当前节点的双亲
    struct BinTreeNode* _pLeft; // 指向当前节点左孩子
    struct BinTreeNode* _pRight; // 指向当前节点右孩子
    BTDataType _data;             // 当前节点值域
};

目录
相关文章
|
16天前
|
存储 搜索推荐 算法
【数据结构】树型结构详解 + 堆的实现(c语言)(附源码)
本文介绍了树和二叉树的基本概念及结构,重点讲解了堆这一重要的数据结构。堆是一种特殊的完全二叉树,常用于实现优先队列和高效的排序算法(如堆排序)。文章详细描述了堆的性质、存储方式及其实现方法,包括插入、删除和取堆顶数据等操作的具体实现。通过这些内容,读者可以全面了解堆的原理和应用。
59 16
|
16天前
|
C语言
【数据结构】二叉树(c语言)(附源码)
本文介绍了如何使用链式结构实现二叉树的基本功能,包括前序、中序、后序和层序遍历,统计节点个数和树的高度,查找节点,判断是否为完全二叉树,以及销毁二叉树。通过手动创建一棵二叉树,详细讲解了每个功能的实现方法和代码示例,帮助读者深入理解递归和数据结构的应用。
65 8
|
2月前
|
C语言
数据结构基础详解(C语言):图的基本概念_无向图_有向图_子图_生成树_生成森林_完全图
本文介绍了图的基本概念,包括图的定义、无向图与有向图、简单图与多重图等,并解释了顶点度、路径、连通性等相关术语。此外还讨论了子图、生成树、带权图及几种特殊形态的图,如完全图和树等。通过这些概念,读者可以更好地理解图论的基础知识。
103 8
|
2月前
|
存储 算法 C语言
数据结构基础详解(C语言): 二叉树的遍历_线索二叉树_树的存储结构_树与森林详解
本文从二叉树遍历入手,详细介绍了先序、中序和后序遍历方法,并探讨了如何构建二叉树及线索二叉树的概念。接着,文章讲解了树和森林的存储结构,特别是如何将树与森林转换为二叉树形式,以便利用二叉树的遍历方法。最后,讨论了树和森林的遍历算法,包括先根、后根和层次遍历。通过这些内容,读者可以全面了解二叉树及其相关概念。
|
2月前
|
存储 算法 C语言
C语言手撕实战代码_二叉树_构造二叉树_层序遍历二叉树_二叉树深度的超详细代码实现
这段代码和文本介绍了一系列二叉树相关的问题及其解决方案。其中包括根据前序和中序序列构建二叉树、通过层次遍历序列和中序序列创建二叉树、计算二叉树节点数量、叶子节点数量、度为1的节点数量、二叉树高度、特定节点子树深度、判断两棵树是否相似、将叶子节点链接成双向链表、计算算术表达式的值、判断是否为完全二叉树以及求二叉树的最大宽度等。每道题目均提供了详细的算法思路及相应的C/C++代码实现,帮助读者理解和掌握二叉树的基本操作与应用。
|
2月前
|
存储 C语言
数据结构基础详解(C语言): 树与二叉树的应用_哈夫曼树与哈夫曼曼编码_并查集_二叉排序树_平衡二叉树
本文详细介绍了树与二叉树的应用,涵盖哈夫曼树与哈夫曼编码、并查集以及二叉排序树等内容。首先讲解了哈夫曼树的构造方法及其在数据压缩中的应用;接着介绍了并查集的基本概念、存储结构及优化方法;随后探讨了二叉排序树的定义、查找、插入和删除操作;最后阐述了平衡二叉树的概念及其在保证树平衡状态下的插入和删除操作。通过本文,读者可以全面了解树与二叉树在实际问题中的应用技巧和优化策略。
|
1月前
|
C语言 C++
C语言 之 内存函数
C语言 之 内存函数
34 3
|
9天前
|
C语言
c语言调用的函数的声明
被调用的函数的声明: 一个函数调用另一个函数需具备的条件: 首先被调用的函数必须是已经存在的函数,即头文件中存在或已经定义过; 如果使用库函数,一般应该在本文件开头用#include命令将调用有关库函数时在所需要用到的信息“包含”到本文件中。.h文件是头文件所用的后缀。 如果使用用户自己定义的函数,而且该函数与使用它的函数在同一个文件中,一般还应该在主调函数中对被调用的函数做声明。 如果被调用的函数定义出现在主调函数之前可以不必声明。 如果已在所有函数定义之前,在函数的外部已做了函数声明,则在各个主调函数中不必多所调用的函数在做声明
25 6
|
29天前
|
存储 缓存 C语言
【c语言】简单的算术操作符、输入输出函数
本文介绍了C语言中的算术操作符、赋值操作符、单目操作符以及输入输出函数 `printf` 和 `scanf` 的基本用法。算术操作符包括加、减、乘、除和求余,其中除法和求余运算有特殊规则。赋值操作符用于给变量赋值,并支持复合赋值。单目操作符包括自增自减、正负号和强制类型转换。输入输出函数 `printf` 和 `scanf` 用于格式化输入和输出,支持多种占位符和格式控制。通过示例代码详细解释了这些操作符和函数的使用方法。
35 10
|
22天前
|
存储 算法 程序员
C语言:库函数
C语言的库函数是预定义的函数,用于执行常见的编程任务,如输入输出、字符串处理、数学运算等。使用库函数可以简化编程工作,提高开发效率。C标准库提供了丰富的函数,满足各种需求。