树以及二叉树的定义和特点

目录

开场白     

树的定义

结点的分类

结点间的关系

树的其他相关概念

树的存储结构

孩子兄弟表示法

二叉树的定义

 二叉树的特点

特殊二叉树

满二叉树

完全二叉树

二叉树的性质

二叉树的存储结构


开场白     

  这一篇文章是关于树的知识,这是一个比较特殊的结构。下面就让我们拿出百分之一百二的精神来学习吧。

        首先,让我们来看一看下面这幅图。

        我们可以看到,左边这颗就是树,只不过它是倒着的,根再上面,叶子在下面。再看看右边,就是我们抽象出来的树型结构,最上面的也是根,最下面的就是我们的叶子。

        无论多高多大的树,那也是从小到大,由根到叶,一点点成长起来的。俗话说“十年树木,百年树人”,可一颗大树又何止是十年这样容易的——哈哈,说到哪里去了,我们现在不是在上生物课,而是要讲一种新的数据结构——树。

树的定义

        之前我们讲的顺序表,链表,这些都是一对一的线性结构,可现实中,还有很多一对多的情况需要处理,所以我们需要学习并研究一种一对多的数据结构——“树”,考虑它的特点以及特性,来解决我们生活中的一些问题。

        树(Tree)是n(n>=0)个结点的有限集。n=0的时候是空树。在任意一颗非空树中:1:有且仅有一个特定的称为根的结点;2:当n>1时,其余结点可分为m(m>0)个互不相交的有限集T1,T2,T3~~~Tm,其中每一个集合本身又是一颗树,并且称为根的子树。

        树的定义其实就是我们再讲栈时提到的递归方法。

结点的分类

        树的结点包含一个数据和它的分支,就是它不仅储存了数据,还储存了和它有关系的结点的地址。结点拥有的子树称为结点的度。度为零的节点称为叶子结点或者终端结点;度不为零的节点称为非终端结点。树的度是树内各个结点的最大的度。

我们来看一看上图,首先A是根节点,它有3个子树分别为B1,B2,B3所以说它的度就是3,然后B1的分支有两条所以它的度为2,同理B2的度为1,D3的度为0,这里我们就不在全部都说了。所以说这里面的最大的度为3,这整颗树的度就为3。

结点间的关系

        结点的子树的根称为结点的孩子,相应的,该节点称为孩子的双亲。  我们还是从上图来举例说明,A就是B1,B2,B3 的双亲,所以B1,B2,B3就是A的孩子,同理B2是C3的父亲,C3是B2的孩子。

        同一个双亲的孩子称为兄弟。结点的祖先就是从根到该节点路径上的所有节点。  可以看到B1,B2,B3的父亲都是A,所以说他们都是兄弟,这也和我们人类的亲缘关系一样。D2的祖先就是从A到它自己的上的所有节点,所以C1,B1,A都是它的祖先。其它的我就不一一举例了,大家其实也很好理解。

        以某节点为根的子树的仍和一个结点都称为该结点的子孙。这个很好理解,因为有了根才有叶子。    

树的其他相关概念

        结点的层次从根开始定义起,根为第一层,根的孩子为第二层。比如某个结点在地N层,则它的孩子就在N+1层。其双亲在同一层的节点互为堂兄弟,就和我们人类的辈分关系一样,辈分相同但又不是亲兄妹的称为堂兄弟。树中结点的最大层次称为树的深度或高度。

树的存储结构

        说到存储结构,在我们学习树型结构之前,我们就已经学习了顺序存储和链式存储两种结构了。

        先来看看顺序存储结构,用一段地址连续的存储单元一次存储线性表的数据元素。这对于线性表来说是很自然的,对于树这样的结构呢?

        树中的某个节点的孩子可能有多个,而且每个节点的孩子的数量也不相同,如果说我们以最大的度的节点来开辟内存空间的话,这样对内存的消耗就很大很大了,如果是后面我们要学习的二叉树还好,如果遇到一些度很大的树的节点,这些方法就不太好,我们尽量还是要做到有多少我们用多少的存储空间。

        不过充分利用顺序存储和链式存储结构的特点,完全可以实现对树的存储结构的表示。我们要了解的有三种方法:双亲表示法,孩子表示法,孩子兄弟表示法。

        下面我们重要讲述孩子兄弟表示法,这个比较好理解。

孩子兄弟表示法

        我们观察一颗树可以发现,任意一棵树,只要它的结点的第一个孩子存在的话就是唯一的,它的兄弟存在的话也是唯一的。所以我们可以定义一个孩子指针指向它的第一个孩子,定义一个兄弟指针指向它右边的第一个兄弟。就像下面这样。

struct TreeNode
{
    datatype val;
    struct TreeNode* child
    struct TreeNode* brother;
}

      

        对于上图的左边这颗树来说,它的表示方法就是右边这种。首先我们可以看到A它只有孩子,没有兄弟则它的孩子节点就指向了左边第一个孩子B,它没有兄弟,兄弟节点就指向空;再来看B,它的孩子节点指向了第一个孩子D,它的兄弟节点指向了C,接下来就是重复的内容了,C的第一个孩子又是E,兄弟指针指向了空~~~ 这样直到J 就完全把整颗树表示出来了。

        其实这个表示方法其实还是有缺陷的,它只能通过双亲结点找到孩子和兄弟,但是无法找到它自己的双亲。其实解决这个方法也很简单,我们只需要再增加一个双亲指针就行了。这个方法就把一颗比较复杂的树表示成了一颗二叉树的形式,这时肯定你不知道二叉树是什么,没关系,下面就让我们来学习一下树的重点内容——二叉树。

二叉树的定义

        二叉树是我们学习数据结构中很重要的一个知识点。它的结构比较特殊,我们先来看一看图片。

       我们可以看到上面这幅图,它的度为2,我们仔细观察,它的每一个节点的度都小于或等于2。我们把这种树就叫做二叉树。

        二叉树是n(n>=0)个节点的有限集合,该集合或者为空集(称为空二叉树),或者由一个根节点和两颗互不相交,分别称为根节点的左子树和右子树的二叉树组成。

 二叉树的特点

 二叉树的特点有:

1.每个节点最多有两颗子树,所以二叉树中不存在度大于2的节点。注意不是只有两个子树,而是最多只有两颗子树。没有子树或者一颗子树也是可以的。

2.左子树和右子树,也要区分它是左子树还是右子树。就像人的双手和双脚,但显然左手和右手,左脚和右脚是不一样的,左手带左手套,右手带右手套,对你的生活影响是完全不同的。

可以看到上面这两颗树是完全不同的。因为二叉树是要区分左右的,对于图一来说3是2的右子树,而图二却相反,3是2的左子树。

特殊二叉树

满二叉树

在一颗二叉树中,如果所有分支节点都存在左子树和右子树,并且所有的叶子都在同一层上,这样的树就叫做满二叉树。

像这样只有最后一层存在叶子结点,其它的节点都存在左右节点的特殊树形结构就是满二叉树,从样子上看就感觉它很完美。

单是每个结点都存在左右子树,不能算是满二叉树,还必须要所有的叶子都在同一层上,这样做到了整棵树的平衡。因此,二叉树的特点有:

1.叶子节点只能出现在最下层,出现在其他层就不可能达到平衡。

2.非叶子节点的度一定是2。

3.在同样深度的二叉树中,满二叉树的结点个数最多,叶子数最多。

完全二叉树

 对一颗具有n个结点的二叉树按层序编号,如果编号i(1<=i<=n)的节点与同样深度的满二叉树中编号为i的节点在二叉树中位置完全相同,则这颗二叉树称为完全二叉树。

这样听起来好像不太好理解,这样我们先来看一看它长什么样子。

观察一下,上面这个完全二叉树有4层,它的前三层就是一颗满二叉树,然后最后一层的叶子节点必须是连续的,中间不能有空的部分。

 像上面这棵树,它的前三层是满二叉树,但是在第四层,5节点的左子树就不存在,导致9和B中介空了出来,所以说上面这颗树就不是满二叉树。

首先从字面上要区分,“完全”和“满”的差异,满二叉树一定是一颗完全二叉树,但完全二叉树不一定是满二叉树。我们一定要理解清楚这句话。

我们再这里也可以总结一下二叉树的特点:

1.叶子结点只能出现在最下两层。

2.最下层的叶子一定集中在左部连续位置。

3.倒数第二层,若有叶子结点,一定都在右部位置。

4.如果节点度为1,则该结点只有左孩子,即不存在右子树的情况。

5.同样结点数的二叉树,完全二叉树的深度最小。

二叉树的性质

性质1:二叉树的第i层至多有2^(i-1)个结点。

比如:第一层为 2^0=1个;第二层2^1=2个;第三层2^3=3个~~~;通过数学归纳法的论证,可以得出二叉树的第i层有至多有2^(i-1)个结点。

性质2:深度为K的二叉树最多有2^k-1个结点(k>=1)。

记住这里是2^k-1,不是2^(k-1)。这里容易混淆,因为这里是算的总结点的个数,就需要用到等比数列的求和公式,简单推导一下就出来了,这里我们就不去推导了。

性质3:对于任何一颗二叉树T,如果终端结点数n0(叶子节点),度为2的节点数为n2,则n0=n2+1;

这个性质是非常重要的,希望大家都能够记住,如果记不住其实我们就画一颗简单的满二叉树或者完全二叉树就可以找到它们的关系了。

这里讲的3个性质都是比较常用的,希望同学们能够记下来。

二叉树的存储结构

二叉树我们一般都选择链式存储结构,二叉树每个结点最多有两个孩子,所以为他设计一个数据域和两个指针域,我们称这样的链表叫做二叉链表。

struct TreeNode
{
    datatype val;
    struct TreeNode* child
    struct TreeNode* brother;
}

我们前面也说了,如果有需要,我们还可以增加一个指向双亲的指针。

遍历二叉树

二叉树的遍历主要要用到递归,所以这里的内容需要对递归有一定的理解能力。

遍历二叉树的方法有3中,分别是前序,中序,后序遍历。

我们这里指讲讲前序遍历,中序和后序其实也和前序遍历差不多,只要弄懂前序遍历,其它两个就不是问题。

前序遍历

规则是若二叉树为空,则空操作返回,否则先访问根节点,然后前序遍历左子树,在前序遍历右子树。具体代码如下。

// 二叉树前序遍历 
void BinaryTreePrevOrder(BTNode* root)
{	

    //如果该节点是空,打印# 再返回
	if (root == NULL)
	{
		printf("# ");
		return;
	}
    //不是空,打印数据域
	printf("%c ", root->data);
    //然后遍历左子树
	BinaryTreePrevOrder(root->left);
    //遍历右子树
	BinaryTreePrevOrder(root->right);
}

中序遍历

规则是若二叉树为空,则空操作返回,从根节点开始,先访问根节点的左子树,再访问根节点,最后访问右子树。

后序遍历

规则是若二叉树为空,则空操作返回,从根节点开始,先访问根节点的左子树,再访问根节点的右子树,最后再访问根节点。

下面的代码就留给同学们自己去写了。后面还有稍难的层序遍历还需要用到队列的知识,我们后面再讲。

总结

        终于到了总结的时间,树这一块的内容,相对于前面的队列和栈就比较复杂了。我们这里也只学习了一些树和二叉树的基本性质和概念。需要学懂树型结构还需要很长的一段路要走。开头我们提到了树的定义,降到了递归子啊树中的应用。提到了子树,结点,度,叶子,分支节点,双亲,孩子,兄弟,深度,层次等等。这些都是需要我们去理解记忆的。

        遍历是二叉树最重要的部分,前序,中序,后序以及层序遍历(这里没有讲)都是需要熟练掌握的知识。要让自己学会用递归去实现它们的代码。这样可以加深我们对递归的理解。

        好了,关于树和二叉树的一些基本知识我们就讲到这里,如果有哪里不正确的地方还请大家指出。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Python 学习 用Python第二册 第9章内容解八皇后问题

----用教授的方法学习 目录 1.八皇后问题 2.状态表示(抽象) 3.检测冲突 4.基线条件 5.递归条件 6.结尾 1.八皇后问题 深受大家喜爱的计算机科学谜题&#xff1a;你需要将8个皇后放在棋盘上&#xff0c;条件是任何一个皇后都不能威胁其他皇后&#xff0c;即任何两个皇后…

利用485缓存器实现两主一丛RS485串行通信

作者:艺捷自动化&#xff0c;其旗下产品有艺捷自动化网站和易为二维码小程序&#xff08;微信&#xff09; 对于工控自动化领域的电气工程师来说&#xff0c;基于RS485的串行通讯是最常见的。绝大部分仪表都能支持这种通讯方式。RS485通讯&#xff0c;是一种异步半双工模式&…

誉天5月红帽战报:恭喜14名学员通过RHCE认证,通过率87.5%!

红帽认证是全球公认的Linux权威认证之一&#xff0c;对于Linux从业者来说具有很高的价值和认可度。旨在评估考生在Linux系统管理和应用方面的专业知识和技能。红帽考试是Linux从业者提升自身技能水平和职业竞争力的重要途径之一。 5月份&#xff0c;誉天14名学员通过了RHCE认证…

css入门宝典

3.1.4 通配符选择器 语法 : *{} 作用 : 让页面中所有的标签执行该样式,通常用来清除间距 例子 : *{ margin: 0; //外间距 padding: 0; //内间距 } 一 CSS基本语法 1基础知识 1.1概述 Css (层叠样式表)是种格式化网页的标准方式&#xff0c; 用于控制设置网页的样式&#xff…

WSL Ubuntu安装TensorFlow-GPU、PyTorch-GPU

在Windows 11的WSL Ubuntu中安装TensorFlow-GPU、PyTorch-GPU 0、WSL Ubuntu安装 在Windows 11的商店中下载即可&#xff0c;此处以Ubuntu22.04.3为例 1、CUDA Toolkit安装 参考公孙启的文章Windows11 WSL Ubuntu Pycharm Conda for deeplearning前往nVidia官网下载CUDA …

transformer模型首次体验代码

前言 首先是安装python&#xff0c;更新pip源到清华源。安装transformer pip install transformer安装jupyter lab&#xff0c;也简单一行 pip install jupyterlab现在不想用anaconda了&#xff0c;因为国内没有源了&#xff0c;国外的又慢。直接用pip吧。 然后开始体验之旅…

DeepDriving | CUDA编程-05:流和事件

本文来源公众号“DeepDriving”&#xff0c;仅用于学术分享&#xff0c;侵权删&#xff0c;干货满满。 原文链接&#xff1a;CUDA编程-05&#xff1a;流和事件 1 CUDA流 在CUDA中有两个级别的并发&#xff1a;内核级并发和网格级并发。前面的文章DeepDriving | CUDA编程-04&…

buildroot编译出错you should not run configure as root

虚拟机版本&#xff1a;ubuntu-22.04.4 问题 buildroot在图形配置后&#xff0c;执行 sudo make开始编译出现以下错误configure: error: you should not run configure as root (set FOenvironment to bypass this check) 在网上看到说在/etc/profile文件中添加以下内容 exp…

Ngunx + Tomcat 负载均衡和动态分离

目录 一、tomcat简介 二、Nginx 负载均衡 1. Nginx 应用 2. Nginx 负载均衡实现原理 2.1 正向代理 2.2 反向代理 2.3 具体过程接收请求&#xff1a;Nginx作为反向代理服务器&#xff0c;接收客户端的请求。选择后端服务器&#xff1a;根据预先配置的负载均衡算法&#xf…

23种设计模式之享元模式

享元模式 1、定义 享元模式&#xff1a;运用共享技术有效的支持大量细粒度对象的复用 2、享元模式结构 Flyweight&#xff08;抽象享元类&#xff09;&#xff1a;通常是一个接口或抽象类&#xff0c;在抽象享元类中声明了具体享元类公共的方法&#xff0c;这些方法可以向外…

从多线程设计模式到对 CompletableFuture 的应用

大家好&#xff0c;我是 方圆。最近在开发 延保服务 频道页时&#xff0c;为了提高查询效率&#xff0c;使用到了多线程技术。为了对多线程方案设计有更加充分的了解&#xff0c;在业余时间读完了《图解 Java 多线程设计模式》这本书&#xff0c;觉得收获良多。本篇文章将介绍其…

几种经典查找算法

几种经典查找算法 顺序查找法二分查找法判定树 二叉查找树&#xff08;BST&#xff09;索引查找B-树B树散列表&#xff08;hash&#xff09;查找 顺序查找法 顺序查找的平均查找长度为&#xff1a; 时间复杂度为0&#xff08;n&#xff09;&#xff1b; 二分查找法 int bin…

CNN学习(7):用C++实现简单不同参数的卷积模型

目录 一、参数说明和计算公式 1、符号约定 2、输出大小计算公式 二、不同类型的卷积 1、输入3*3*1&#xff0c;卷积核3*3*1&#xff0c;输出1*1*1 &#xff08;1&#xff09;实现代码 &#xff08;2&#xff09;代码说明 2、输入4*4*1&#xff0c;卷积核3*3*1&#xff…

环保评A的意义与价值

环保评A&#xff0c;这个看似简单的称谓&#xff0c;背后却蕴藏着深厚的环保理念和实践标准。在当今社会&#xff0c;环保已经成为一项全球性的议题&#xff0c;各国都在努力推动绿色发展&#xff0c;实现可持续发展目标。那么&#xff0c;环保评A究竟是全国性的认证还是地方性…

Java SSTI服务端模版注入漏洞原理与利用

文章目录 前言Velocity基础语法基础示例命令执行 靶场实践漏洞代码漏洞验证检测工具 FreeMarker基础示例漏洞示例CMS案例 Thymeleaf基础示例漏洞示例安全方案 总结 前言 SSTI&#xff08;Server Side Template Injection&#xff09;全称服务端模板注入漏洞&#xff0c;在 Jav…

开放式耳机值得入手买吗?可以对比这几款开放式耳机看看

居家办公时&#xff0c;选择一款合适的耳机能够有效地提高工作效率。入耳式耳机虽然能够有效地隔绝外界噪音&#xff0c;但长时间佩戴会对耳朵造成负担&#xff0c;甚至引发耳道感染。而头戴式耳机虽然能够提供更好的音质&#xff0c;但体积较大&#xff0c;佩戴起来不够灵活。…

PyTorch -- Batch Normalization(BN) 快速实践

Batch Normalization 可以 改善梯度消失/爆炸问题&#xff1a;前面层的梯度经过多次传递后会变得非常小(大)&#xff0c;从而导致网络收敛速度慢(不收敛)&#xff0c;应用 BN 可缓解加速网络收敛&#xff1a;BN 使得每个神经元的输入分布更加稳定减少过拟合&#xff1a;BN 可减…

求导,积分

求导公式&#xff1a; 复合函数求导法则&#xff1a;两个函数导函数的乘积. 例如&#xff1a;f(x)2x1,f(x)2,g(x)x^24x4,g(x)2x4 那么复合函数&#xff1a; g(f(x))(2x1)^24(2x1)4 把&#xff08;2x1&#xff09;看做整体,则g2(2x1)4 然后再求&#xff08;2x1&#xff09;的导函…

LeetCode | 2879.显示前三行

在 pandas 中&#xff0c;可以使用 head() 方法来读取 DataFrame 的前几行数据。如果想读取指定数量的行&#xff0c;可以在 head() 方法中传入一个参数 n&#xff0c;读取前 n 行 import pandas as pddef selectFirstRows(employees: pd.DataFrame) -> pd.DataFrame:retur…

Dictionary 字典

文章目录 一、什么是字典1.1 字典的创建方式 一、什么是字典 字典&#xff1a; 用来存储数据&#xff0c;与列表和元组不一样的是&#xff0c;字典以键值对的形式对数据进行存储&#xff0c;也就是 key 和 value。相当于 Java 中的 Map。 注意&#xff1a; 1、 key 的值不可重…