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

数据结构之二叉树-初见介绍

目录

前言

一、树

  1、树的概念

  2、树的相关术语)(标红的术语要着重记忆)

  3、树的结构

  4、树的代码表示

  5、树形结构实际运用场景

二、二叉树

  1、二叉树的概念

  2、特殊的二叉树

    2.1 满二叉树

    2.2 完全二叉树

  3、二叉树的存储结构

    3.1 顺序结构

    3.2 链式结构

结束语


前言

      前面我们花了两篇文章讲解了数据结构中的栈和队列,不管是最开始数据结构所学的顺序表和链表,还是栈和队列,这些都是属于线性表的类别。而这次我们所讲解的数据结构-二叉树是不属于线性表的非线性数据结构。
      前面的栈和队列由于和顺序表链表有些相似,所以讲解起来还是比较轻松容易的,而这次的二叉树对于我们刚学习数据结构是一个完全陌生的概念,而且本身二叉树的内容也非常之多,不仅有实现顺序结构二叉树-堆,也有实现链式结构二叉树,这两个部分都需要拿出来单独讲解。本篇文章主要是先介绍树以及二叉树的相关概念以及专有名词的讲解。

一、树

  1、树的概念

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

  2、树的相关术语)(标红的术语要着重记忆)

      (1)结点的度:一个结点有几个孩子,他的度就是多少;比如A的度为6,F的度为2,K的度为0
      (2)叶子结点/终端结点:度为0的结点称为叶结点;如上图:B、C、H、I... 等结点为叶结点
      (3)分支结点/非终端结点:度不为0的结点;如上图:A、D、E、F、G.. 等结点为分支结点
      (4)父结点/双亲结点:若一个结点含有子结点,则这个结点称为其子结点的父结点;如上图:A是B的父结点
      (5)子结点/孩子结点:一个结点含有的子树的根结点称为该结点的子结点;如上图:B是A的孩子结点
      (6)兄弟结点:具有相同父结点的结点互称为兄弟结点(亲兄弟);如上图:B、C 是兄弟结点
      (7)树的度:一棵树中,最大的结点的度称为树的度;如上图:树的度为6。注意:A作为整个图最开始的根节点的度可能不是最大的,所以数的度并不是看最上面的根,而是要找中间最大节点的度。
      (8)结点的层次:从根开始定义起,根为第1层,根的子结点为第2层,以此类推;
      (9)树的高度或深度:树中结点的最大层次;如上图:树的高度为4
      (10)堂兄弟节点:双亲在同一层的节点互为堂兄弟;如上图:H、I互为堂兄弟节点
      (11)结点的祖先:从根到该结点所经分支上的所有结点;如上图:A是所有结点的祖先
      (12)子孙:以某结点为根子树中任一结点都称为该结点的子孙;如上图:所有结点都是A的子孙
      (13)路径:一条从树中任意节点出发,沿父节点-子节点连接,达到任意节点的序列;比如A到Q的路径为:A-E-J-Q;H到Q的路径H-D-A-E-J-Q
      (14)森林:由m(m>0)棵互不相交的树的集合称为森林

  3、树的结构

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

      在树形结构中,子树之间不能有交集,否则就不是树形结构,这种叫做非树形结构,如下图所示:

      所以我们知道了树的特点为:
      (1)子树是不相交的(如果存在相交就是图了,图在以后的学习会有讲解)
      (2)除了根结点外,每个结点有且仅有一个父结点
      (3)一棵N个结点的树有N-1条边

  4、树的代码表示

      树结构相对线性表就比较复杂了,要存储表示起来就比较麻烦了,既然保存值域,也要保存结点和结点之间的关系,实际中树有很多种表示方式:

//明确规定树的度为N
#define N 4;
struct TreeNode
{int val;struct TreeNode* subs[N];
};

      第一种写法的前提是明确规定了树的度为N,也就是说一个根结点的子结点数不能超过该值,用指针数组即可表示。

struct TreeNode
{int val;vector<struct TreeNode*> subs;
};

      第二种写法就不需要规定树的度,每个根结点可有任意个子结点,但这个写法是基于C++来实现的,所以现阶段我们不会利用这个写法。

struct TreeNode
{int val;struct Node* child; // 左边开始的第⼀个孩⼦结点 struct Node* brother; // 指向其右边的下⼀个兄弟结点
};

      第三种方法也不需要规定树的度,而且这个方法非常的巧妙,不仅不需要利用C++的相关知识,而且每个根结点也可有任意个子结点,这个也是很多人都在用的方法,被叫做左孩子右兄弟表示法
      

      由第二个图我们会发现:无论一个父亲结点有多少个孩子,child指针永远只会指向左边第一个孩子,而父亲的其他孩子就由前一个孩子的brother指针来指向当一个结点没有兄弟时则指针brother置为NULL,而当一个结点的child指针没有指向下一个结点也就说明该结点为叶子节点
      举一个容易理解这个图的例子:在以前生活的家庭比较贫困,大部分家庭都会生很多个孩子,三四个四五个这种,为了赚更多的钱来维持生计。但如果同时就生出这么多孩子那父母就必须要同时带导致自己抽不出时间去赚钱养家,这样肯定是不行的。所以父母都会先生出一个孩子养到五六岁七八岁的时候再生一个孩子,生出的孩子父母就不用专门照顾了就由老大孩子进行照顾,父母只需要照顾老大然后去赚钱养家。当老二也到一定年纪后父母就会继续生第三个孩子,让老二进行照顾以此类推。这样不仅不会增加父母同时养多个孩子的负担,而且孩子们都能为家里出力。这些孩子之间的关系就和上面的图一样是亲兄弟brother。也就是说我可以通过老大孩子找到老二,通过老二找到老三等等一直找下去,当一个孩子的brother没有指向时就说明这个孩子是最小的了。
      讲完这个例子相信大家对上面这张图应该就有了更清晰的认识了,

  5、树形结构实际运用场景

      文件系统是计算机存储和管理文件的一种方式,它利用树形结构来组织和管理文件和文件夹。在文件系统中,树结构被广泛应用,它通过父结点和子结点之间的关系来表示不同层级的文件和文件夹之间的关联。

二、二叉树

  1、二叉树的概念

      在树形结构中,我们最常用的就是二叉树,一棵二叉树是结点的一个有限集合,该集合由一个根结点加上两棵别称为左子树右子树的二叉树组成或者为空。

      从上图可以看出二叉树具备以下特点:
      (1)二叉树不存在度大于2的结点
      (2)二叉树的子树有左右之分,次序不能颠倒,因此二叉树是有序树
     

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

  2、特殊的二叉树

    2.1 满二叉树

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

    2.2 完全二叉树

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

      由图我们就发现完全二叉树相较于满二叉树唯一不同在于:最后一层不需要满节点,但是一定要保证是连续的,什么意思呢?

      像上面这种二叉树就不是完全二叉树,最后一层的结点并不是连续的。

      根据满二叉树的特点可知:
      (1)若规定根结点的层数为1,则一棵非空二叉树的第 i 层上最多有2^{i-1}个结点
      (2)若规定根结点的层数为1,则深度为 h 的二叉树的最大结点数是2^{h}-1
      (3)若规定根结点的层数为1,具有 n 个结点的满二叉树的深度h=\log _{2}(n+1) 

  3、二叉树的存储结构

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

    3.1 顺序结构

      顺序结构存储就是使用数组来存储,一般使用数组只适合表示完全二叉树,因为不是完全二叉树会有空间的浪费,完全二叉树更适合使用顺序结构存储。

      那这里就有人问了用数组咋表示完全二叉树啊?而且这数组就在一排怎么判断谁和谁有父子关系啊?

      这就需要用到数组的下标了:
      假设父亲在数组中的下标为:i;
      则左孩子在数组中的下标为:2 * i + 1;
      则右孩子在数组中的下标为:2 * i + 2;

      不确定的朋友可以把公式套到上面的图进行·证明,会发现的确是如此的,那为什么会有这样的公式呢?原因就在于完全二叉树是连续的,结点不会存在中间断开的情况。

      那我们知道孩子在数组中的下标能否求出对应父亲的下标,其实也是可以的
      假设孩子在数组中的下标为:j;
      则父亲在数组中的下标为:(j - 1) / 2 ;

      那有些人就问了:一个父亲可能有左孩子也可能有右孩子,难道不需要先判断一下吗,这其实利用到的就是 int 类型在除法中会进行取整,(3 - 1) / 2 == (4 - 1) / 2 == 1,所以不需要先判断。

      上面一图就是非完全二叉树在数组中的存储,我们会发现的确有空间的浪费,所以一般完全二叉树更适合使用顺序结构来进行存储。

    3.2 链式结构

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

结束语

      到此我们对树以及二叉树的概念就讲解完了,本篇主要是先熟悉一下二叉树是什么,结构长什么样,在下一篇文章我们就要讲解对顺序结构二叉树进行实现,也就是堆的讲解。希望这篇文章对大家学习数据结构有所帮助!

http://www.dtcms.com/a/564566.html

相关文章:

  • 【Java 开发日记】finally 释放的是什么资源?
  • VsCode中终端无法运行前端命令
  • 【鸿蒙开发】鸿蒙 ArkTS 语言从零到一完整指南
  • 门户网站建设公司网页设计风格分类
  • 综合整理:pdf预览显示:你尝试预览的文件可能对你的计算机有害。如果你信任此文件以及其来源,请打开此文件以看其内容,如何解决以正常预览文件
  • 微服务拆分之SpringCloud
  • Unity与iOS原生交互开发入门篇 - iOS原生弹窗与回调
  • 企业网站推广在哪里办成免费crm推广网站
  • 本地的赣州网站建设网站访问量asp
  • 总局核名的办理条件
  • 不只是计算:昇腾算子开发中的内存管理艺术
  • 深入解析 Spring Boot 自动配置:原理、实践与进阶​
  • 【Unity卷轴特效实现、原理、与深度解析】
  • STM32 串口中断接收原理与实战详解:从配置到中断服务函数全流程解析
  • 【Linux系统】C/C++的调试器gdb/cgdb,从入门到精通
  • 从被搜索到被推荐:GEO重塑可见性逻辑
  • 如何为 Oracle 数据库配置 TLS/TCPS
  • 阿里云网站备案注销吗大数据做网站
  • pc网站做app京东湖北网站推广服务
  • 测试环境与正式环境同样的机器显示不同的网络问题
  • HTTP_HTTPS协议
  • Linux高效备份:tar与gzip完全指南
  • Java中的File类
  • 四、Linux设备驱动介绍
  • 视频生成模型发展历程:从GAN到Sora的技术革命之路
  • SQL之表的查改(下)
  • CV论文速递: 覆盖医学影像分析、视频理解与生成、3D场景理解与定位等方向! (10.27-10.31)
  • Redis(四):缓存击穿及其解决方案(SpringBoot+mybatis-plus)
  • 突破局域网限制,Websocket 服务远程访问cpolar新方案
  • 科普网站建设方案网站容易被百度收录