大家好,很高兴又和大家见面啦!!!
从今天开始,我们将进入第五章的内容——树与二叉树的学习。
我们之前学习到的线性表、栈和队列、数组、串这些数据结构,它们的元素在逻辑上都是呈现线性关系的,也就是结构中的元素与元素之间都是一对一的关系,但是现在我们要学习的树这种数据结构元素与元素之间则是一对多和多对一的关系。
我们知道现实生活中的树都是从种子开始,先是向下生根,之后向上生长树干,随后从树干上开始分化出多根树枝,最后在树枝上再长出更多的树叶。对于一棵树而言,下往上看它有且仅有一个树干,但是它可以有很多的树枝和树叶,树干与树枝和树叶之间呈现的是一对多的关系,而从上往下看,很多的树叶可以生长在同一根树枝上,很多的树枝可以生长在同一根树干上,因此树叶与树枝是多对一的关系,同理树枝与树干也是多对一的关系。如下图所示:

一棵树为了能够存活,它会从树干的底部的树根中继续向下分化出多个分支去寻找水源,而每个分支上还能继续分化出更多的分支,因此从树干往下看,树根与分支之间是属于一对多的关系,当我们从下往上看时,分支与树根之间则是多对一的关系。
我们不难发现,在现实生活中的树,每棵树的结构都是一对多和多对一的关系。之前我们也提到过计算机语言就是从计算机的角度来描述这个世界,因此,在计算机中,我们同样把数据之间在逻辑上呈现出的一对多和多对一的关系的这种逻辑结构称之为树。
树对我们来说既熟悉又陌生,现在我们仅仅知道它的逻辑结构,而其他的内容,我们却一无所知。因此,在今天的篇章中我们将会学习树的一些基本概念。接下来我们就开始今天的内容吧!!!
树是n(n>=0)个结点的有限集。当n=0时,称为空树。在任意一棵非空树种应满足:

从树的定义中我们可以看到,它的定义是一种递归定义,即在树的定义中又用到了其自身,树是一种递归的数据结构。树作为一种逻辑结构,同时也是一种分层结构,如下所示:

从图中我们可以看到,树具有以下两个特点:
树适合于表示具有层次结构的数据。树中的某个结点(除根结点外)最多只和上一层的一个结点(即其父结点)有直接关系,根结点没有直接上层结点,因此在n个结点的树中有n-1条边,而树中每个结点与其下一层的零个或多个结点(其子女结点)都有直接关系。
在线性表中,我们将数据之间的关系称为前驱和后继,除了第一个元素外,其他的每个元素都有且仅有一个直接前驱,除了最后一个元素外,其他元素都有且仅有一个直接后继。但是在树这种逻辑结构中,结点直接的关系并不是用前驱和后继来进行描述的,当我们在描述一棵树时,我们会将人类的亲缘关系带入到树的各个结点中,如下所示:
双亲:一个结点它的直接上层结点(直接前驱结点)就是它的双亲结点,也称为父结点 孩子:一个结点它的直接下层结点(直接后继结点)就是它的孩子结点 祖先:一个结点的父结点的父结点就是这个结点的祖先结点 子孙:一个结点是它祖先结点的子孙结点 兄弟:有同一个父结点的结点之间互为兄弟结点 堂兄弟:兄弟结点的孩子结点互为堂兄弟结点
不知道大家有没有听过《爸爸的爸爸叫什么》这首歌,在这首歌的歌词中就很好的介绍了人类之间的亲缘关系:
爸爸的爸爸叫什么,爸爸的爸爸叫爷爷 爸爸的妈妈叫什么,爸爸的妈妈叫奶奶 爸爸的哥哥叫什么,爸爸的哥哥叫伯伯 爸爸的弟弟叫什么,爸爸的弟弟叫叔叔 爸爸的姐妹叫什么,爸爸的姐妹叫姑姑 妈妈的爸爸叫什么,妈妈的爸爸叫外公 妈妈的妈妈叫什么,妈妈的妈妈叫外婆 妈妈的兄弟叫什么,妈妈的兄弟叫舅舅 妈妈的姐妹叫什么,妈妈的姐妹叫阿姨 爷爷爸爸的爸爸叫爷爷,奶奶爸爸的妈妈叫奶奶 伯伯爸爸的哥哥叫伯伯,叔叔爸爸的弟弟叫叔叔 姑姑爸爸的姐妹叫姑姑,外公妈妈的爸爸叫外公 外婆妈妈的妈妈叫外婆,舅舅妈妈的兄弟叫舅舅 阿姨妈妈的姐妹叫阿姨……
现在大家可能会对这个祖先有些好奇,为什么它不直接叫爷爷结点呢?这是因为这个祖先的含义并不止是父结点的父结点,而是一个结点的所有与它的父结点有关系的上层结点。换成人类亲缘关系来理解就是我的爷爷是我的祖先,我的爷爷的爸爸也是我的祖先,我的爷爷的爷爷更是我的祖先,也就是爷爷辈即以上辈分且与我有血缘关系的人都是我的祖先。
文字的表述显得有些许苍白了,为了更好的区分这些关系,我们直接通过具体的例子来进行说明,如下所示:

在这棵树中,结点A作为树的根结点,它与其它结点的关系为:
结点B与其它结点的关系为:
结点D与其它结点的关系为::
结点H与其它结点的关系为::
通过这个例子相必大家应该对这些关系的理解更加深刻了吧。结点的关系我们先介绍到这里,接下来我们继续来看一下在树中的其它的基本术语;
在树中,因为数据元素在存储时逻辑上是呈现树状的,因此,对于不同的部分也有其对应的术语,如下所示:
结点的度:树中的一个结点的孩子个数称为该结点的度; 树的度:树中结点的最大度数称为树的度; 分支结点:度大于0的结点称为分支结点,又称非终端结点; 叶结点:度为0的结点称为叶结点,又称终端结点; 结点的层次:从树根开始定义,根结点为第1层,它的子节点为第2层,以此类推。 结点的深度:从根结点开始自顶向下逐层累加; 结点的高度:从叶结点开始自底向上逐层累加; 树的高度(或深度):树中结点的最大层数。
以上这些术语都是对于同一颗树而言,下面我们通过图像来加深对这些术语的印象:

这里我们需要注意的是以下两几点:
对于不同的树而言,它们也有对应的术语:
有序树:树中结点的各子树从左到右是有次序的不能互换; 无序树:树中结点的各子树从左到右是无次序的可以互换; 森林:m(m>=0)棵互不相交的树的集合。
我们还是通过图片来对这些术语进行进一步的理解:

在这三个术语中我们需要注意以下几点:
以上这三个基本术语描述的是树的类型以及树与森林的关系,我们需要理解有序树和无序树具体指的是什么,以及树和森林如何相互转换。
在树中还有两个基本术语,如下所示:
路径:树中两结点之间的路径是由这两个结点之间所经过的结点序列构成的 路径长度:路径上所经过的边的个数
下面我们还是通过图来进一步加深对这些概念的印象,如下所示:

在路径和路径长度中我们需要注意的点有:
现在我们就介绍完了树中的一些基本概念,在接下来的内中我们会不断的接触这些概念,因此这些内容不需要刻意的去记忆,大家通过这些图片对一些概念进行理解就行。
在树中,度为m的树和m叉树这两个概念我们经常容易混淆,因此为了方便大家后续的学习,我们现在直接将它给攻克掉。
度为m的树:指的是一棵树中度数最多的结点它的度数为m的树,因此该树中至少有1个结点的度为m,所以它肯定是非空树;m叉树:指的是一颗树的度最多为m,因此该树中可以没有度为m的结点,所以m叉树也可以是空树;
下面我们通过图像来进一步区分它们之间的区别:

从集合的角度来理解它们二者的区别的话,我们可以认为度为m的树是m叉树的子集。以3叉树为例,在上图中可以很直观的看到,3叉树包含空树、度为0的树、度为1的树、度为2的树以及度为3的树;
从结点的角度来看的话,则可以认为度为m的树最少肯定有一个根结点和m个子结点;而m叉树只需要保证树的度不超过m即可,因此m叉树可以是一棵空树。
它们二者的异同点可以总结为下面这个表格:
度为m的树 | m叉树 |
|---|---|
任意结点的度<=m(最多m个孩子) | 任意结点的度<=m(最多m个孩子) |
至少有一个结点度=m(有m个孩子) | 允许所有结点的度都<m |
一定是非空树,至少有m+1个结点 | 可以是空树 |
对于一棵树而言,它具有以下最基本的性质:
如果我要计算一棵树结点的总数,我只需要把根结点及其下方的所有结点加起来就可以了。为了方便理解,我们以下面这棵树为例:



在有n个结点的树中,从叶结点开始往上走,每一个结点都只与一个上层结点有直接联系,因此我们可以得到结论:
而根结点没有与之对应的上层结点,也就是根结点的上方没有变,因此我们可以得到结论:

在最多的情况下该树的每一层的每一个结点的度都为m,因为每一层的结点数都是上一层的结点数与度数的乘积,而这棵树中所有的结点的度数都为m因此从第二层开始,每一层的结点数都是上一层的结点数×m,如下所示:





这条性质的第一点这里我们就不需要再次证明了,我们来看一下性质的第二点,高度为h,度为m的树,在结点最少的情况下就是只有一个结点的度为m,其它结点的度都为1,如下所示:



今天的内容到这里就全部结束了,在今天的内容中我们详细介绍了树的一些基本的概念,通过今天的学习,我们初步认识了树这种递归型的数据结构,同时也知道了它的一些基本术语和性质。如果大家喜欢博主的作品,可以点赞、收藏加评论支持一下博主,当然也可以转发给身边需要的朋友。在下一篇内容我们将开始学习二叉树的一些基本知识点,大家记得关注哦!!!最后感谢大家的支持,咱们下一篇再见!!!