树的相关概念

Posted 仪式黑刃

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了树的相关概念相关的知识,希望对你有一定的参考价值。

 这一次将以树作为主题,来讨论相关的术语和操作。而无论在学什么东西之前,都要有一个动机——用来解答为什么要学这个,否则将会漫无目的,迷茫不可终日。

 

在此前所接触到的两种主要的数据结构,也就是向量(顺序表or数组)以及列表(链表,栈,队列),从分类上讲,都属于所谓的线性结构,而我们很快就会看到,树结构并不是完全的线性结构,因此这部分内容将是这门课的又一里程碑。在进入这部分内容之前,我们应该首先来回答一个问题:此前所提到的向量和列表,难道不够用么?

 

没错的确如此我们来看一下这两种结构典型的几个操作第一类也就是静态操作以查找作为代表而第二类呢是动态操作——插入or删除很显然向量的静态操作非常快以二分查找为例可以做到O(logN)的效率然而在插入和删除的时候效率都非常的差这个结论是显然的在前面链表的文章里做过说明也要注意到列表则呈现出完全对称的特性——如果要在列表中进行查找无论有序无序最坏情况下要O(N)时间而得益于列表的访问方式一旦能给定一个具体位置插入删除只需要在局部进行只花费常数时间

这也就是说,无论向量和列表,都无法兼顾静态和动态操作的同时高效性,而如何将二者的优势结合起来,也正是我们接下来要讨论的。不难猜出来,解决之道恰好就是“树”这种数据结构。它可以认为是列表的列表:List <List> ,也可以认为是二维的列表:List2。因为这个特征,可以认为树不完全是我们此前所提到的线性结构,但同时也带有一定的线性特征。为了与后面的图结构相区别,不妨称为“半线性结构”。

 

应用

实际上对于树形结构,每个人都不陌生,比如此前说过的以RPN为典型的表达式运算中,可以把后缀表达式直接表示成一棵树,例如1+2就可以表示为

 

如果再乘3,就可以表示成这样

 

这样一个形式。另外,小到文件系统的目录,大到整个Internet的域名结构,都可以表示为这样一棵树

 

对于大学,霍格沃茨学院相对于下属的各个院系,可以表示成这样。

 

 

这给人一个印象:树是按照层次关系来组织数据的一种方式。

 

从离散数学的角度看,树结构不过是一类特殊的图,也是定义在一堆元素之间的二元关系,如果2个元素有关系,就引入一条边,当然还有其他的一些限制条件。这些数据元素,称为顶点(Vertex),对了,这里的vertex和之前的node是有区别的,虽然也有联系——每一个vertex都将以node的形式在程序中被实现。不过这里说的树和图论中的树有所区别。在这里,要为每一棵树指定一个唯一的顶点,称之为根。

 

 

ri称作r的孩子,ri之间互称兄弟,r为其父亲,d=degreer)是r的(出)度,直观看来就是r所有的孩子的数量。有了这些定义,自然会想到:顶点的数目,各个顶点的度数,以及边的数目之间有什么样的关系呢?可以通过归纳证明得出一个结论:

e = ∑r∈V  degree(r)= n - 1 = θ(n) 

也就是说,一棵树中所含的边数,恰好等于各个顶点的度数之和,也等于总顶点数-1。这个定理之所以重要,不在于公式的细微之处,而在于它告诉我们——树中的边数与其顶点的个数是同阶的,因此在衡量复杂度的时候就可以用顶点数作为参考。

 

父与子的关系按照刚才的定义,是十分明确的,问题在于兄弟之间的关系,这十分重要。并且,这也是我们在计算机中实现和维护的树结构与数学中的树之间的又一区别。对兄弟按次序编号,使之成为一个序列。

 

以上,只是从递归嵌套的角度定义了树,这种定义虽然简明,但是并不直观,因为我们并没看到树结构和一般的图结构在拓扑上到底有什么不同。下面就从连通性和无环型两个角度来讨论树的特性。

 

路径+环路

先说路径(path)的概念,简单来讲就是n个点连在一起就构成一条路径,也称为“通路”,像这样:

 

这样的路有一个名为“长度”的指标,就是构成这条路的所有边数。(不过在早期文献中,更多以节点的数目衡量长度)。在所有路径中,会有一些特殊情况——为首的顶点和末尾点重合,那么这条路径就构成了一个循环,也因此成为环路(loop),

 

 

 

 

连通+无环

 如果任意两个点都彼此相连,就称它为连通图(connected graph),那肯定,这里面的边不能太少,反之,如果有太多的边,就更容易出现环路。

 

看到这里,可能会不禁问道:这都是图的概念,和树有什么关系呢?实际上——不仅有关系,而且十分密切,确切地讲,所谓的“树”,就是在无环和连通之间达到平衡的一种特定的图,可以这样来概括树:

 

现在一一解释。因为无环,所以边数不会太多,同时,因为连通所以边数不会太少,在保证连通的前提下,能保证边数最小;而在杜绝环路的前提下,树又能使用尽可能多的边。那作为这些性质的一个推论,很自然的,任何一个节点v与树根之间都存在唯一的路径,因此在记录这条路径时,往往省去根结点,pathv,r)=pathv)。这个推论相当重要,因为既然存在唯一的路径,每个节点也就因此有一个唯一的指标——这条路径的长度。

 

比如这样一棵树中,每一个点都有一个指标,对应于从它到顶点的路径长度。

 

这也就引出接下来要说的有关“深度”和“层次”的相关概念。

 

深度+层次

 每一个节点必然有唯一一条路径到达整棵树的根,同时,在递归地构造一棵树时,某个节点也会在某个时刻变成它子树的根,也就是说——任意一个节点都对应了一棵子树,同时对应到树根的路径,因此,这三者是同一件事,在不致歧义的前提下我们可以将它们彼此指代,也就是pathv)~v~subtree(v)。既然任何节点都会以它所对应的那条通路的长度作为指标,而这样一个指标也很好地体现了从根节点往下深入的程度。因此我们把这条路径的长度形象地称为这个节点在树中的深度。如图,

 

也就是depthv=|path(v)|。如果从根到一个节点的路上还有其他点,那这些点称为这个节点的祖先。反过来,这个节点是他前面点的后代。这里的概念都是包括这个节点自身的,如果将这个点去掉,就称为真祖先or后代,为了理解方便,可以联想一下集合论中子集和真子集的区别。根据这些内容我们可以知道,对于一个节点,在他之上的某一个特定层次,只有一个祖先,然而在他之下的一个特定层次,未必只有一个后代,这也就是之前所谓的“半线性”。

 

对于全树的根节点,一定是任意节点的祖先,也就是公共祖先,深度为0,它没有祖先;而反过来,有些节点也没有后代,这样的节点称为叶节点。注意,在树中叶子节点是必然存在的,否则树中就会包含无穷多个节点。那既然深度有限,必然有最大值,所有叶子深度的最大值被称为树的“高度(height)”,就是最靠下的那个叶子的深度。高度这一概念也可以推广至任何一颗子树,如此定义的树高也称为“根节点的高度”,这几个概念比较容易混淆,所以最好记住这张图。btw,空树高度取-1

 

现在回过头观察一般性的节点,有这样一个事实:depth(v)+heightv<=heightT),一个节点的高度与深度之和不会超过全树的高度,从上面的图中很好理解。那这个式子什么时候取等号呢?你所给出的条件是否是充要条件呢?这个思考就当作闲暇时的消遣吧。

以上是关于树的相关概念的主要内容,如果未能解决你的问题,请参考以下文章

数据结构之树以及二叉树的相关概念

树的相关概念

树的定义及相关概念

数据结构(C语言版)严蔚敏(树的相关概念笔记)

数据结构——树的相关概念和MySQL索引

数据结构(C语言版)严蔚敏(树二叉树的相关概念笔记)