《大话数据结构》笔记(6-1)--树:树
Posted lyu0709
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《大话数据结构》笔记(6-1)--树:树相关的知识,希望对你有一定的参考价值。
代码实现:
第六章 树
树的定义
![](https://image.cha138.com/20210609/117423fec367466abbeaca466dffcae2.jpg)
![](https://image.cha138.com/20210609/d0920786151d4bbd8d37120caed371e1.jpg)
树的结点包含一个数据元素及若干指向其子树的分支。
结点拥有的子树数称为结点的度(degree)。
度为0的结点称为叶结点(Leaf)或终端结点;度不为0的结点称为非终端结点或分支结点。
除根结点之外,分支结点也称为内部结点。
树的度是树内各结点的度的最大值。
![](https://image.cha138.com/20210609/8c4d087babb340b3bde7624a609dd95a.jpg)
结点的子树的根称为该节点的孩子(Child),相应的,该结点称为孩子的Parent
同一个Parent的孩子之间互称兄弟(Sibling)。
结点的祖先是从根到该结点所经分支上的所有结点。以某结点为根的子树中的任一结点都称为该结点的子孙。
结点的层次(Level)从根开始定义起。其Parent在同一层的结点互为堂兄弟。
树中结点的最大层数称为树的深度(Depth)或高度。
![](https://image.cha138.com/20210609/50476702cb9b4fa6a28e9f304aafdaba.jpg)
如果将树中结点的各子树看成从左至右是有次序的,不能互换的,则称改树为有序树,否则称为无序树。
森林(Forest)是m(m>=0)棵互不相交的树的集合。对树中每个结点而言,其子树的集合即为森林。
![](https://image.cha138.com/20210609/893f4f8322c446659865cbe053574fd2.jpg)
树的抽象数据类型
![](https://image.cha138.com/20210609/ae7e3fa2dac042288107c3df545d88e2.jpg)
树的存储结构
双亲表示法
假设以一组连续空间存储树的结点,同时在每个结点中,附设一个指示器指示其双亲结点到链表中的位置。
![](https://image.cha138.com/20210609/2a6fca1b633047ec85973f364c4f70df.jpg)
结点结构定义代码:
![](https://image.cha138.com/20210609/dea6668541c041648e54a7f8a6d3253e.jpg)
![](https://image.cha138.com/20210609/dab4923cf65f4c3592885425efe39bea.jpg)
约定根结点的位置域设置为-1
![](https://image.cha138.com/20210609/f285479c6eb1472b9259fff0994ff3fe.jpg)
根据结点的parent指针很容易找到它的双亲结点,所用的时间复杂度为O(1);如果想要知道结点的孩子是什么,则需要遍历整个结构才行。
改进:
可以把此结构扩展为双亲域、长子域、右兄弟域等。
存储结构的设计是一个非常灵活的过程,一个存储结构设计的是否合理,取决于基于该存储结构的运算是否适合、是否方便、时间复杂度好不好等。
孩子表示法
每个结点有多个指针域,其中每个指针指向一棵子树的根结点,我们把这个方法叫做多重链表表示法。
由于树的每个结点的度不相同,所以有两种方案来解决。
方案一
指针域的个数等于树的度。
![](https://image.cha138.com/20210609/5f6b49dab14f422e8c639b5310417880.jpg)
![](https://image.cha138.com/20210609/b254a11a54924a7c9dd1d5235ca6f6a0.jpg)
这种方法对于树中各节点的度相差很大时,显然是浪费空间的。不过如果树的各结点度相差很小时,就意味着开辟的空间被充分利用了,这时存储结构的缺点反而变成了优点。
方案二
每个结点指针域的个数等于该结点的度。
![](https://image.cha138.com/20210609/6ac4f68e8b4c425691711108ca3f3b91.jpg)
![](https://image.cha138.com/20210609/3b3b07e09b4e4c2ea90a9f6a29eb0db0.jpg)
这种方法克服了浪费空间的缺点,对空间利用率是提高了,但是由于各个结点的链表是不相同的结构,加上要维护结点的度的数值,在运算上就会带来时间上的损耗。
有没有什么方法,既可以减少空指针的浪费又能使结点各结构相同?
孩子表示法
把每个结点的孩子结点排列起来,以单链表作为存储结构,则n个结点有n个孩子链表,如果是叶子结点则此单链表为空。然后n个头指针又组成一个线性表,采用顺序存储结构,存放进一个一维数组中。![](https://image.cha138.com/20210609/ad0657bc7c93437591e733f7e0846ded.jpg)
![](https://image.cha138.com/20210609/ad0657bc7c93437591e733f7e0846ded.jpg)
为此,需要设计两种结点结构,一个是孩子链表的孩子结点
另一个是表头数组的表头结点![](https://image.cha138.com/20210609/5082dc7642e54fff88c4fda3bd2a9eeb.jpg)
![](https://image.cha138.com/20210609/810e08f6182c40918615e7f82b9f25e5.jpg)
![](https://image.cha138.com/20210609/5082dc7642e54fff88c4fda3bd2a9eeb.jpg)
孩子表示法的结构定义代码:
![](https://image.cha138.com/20210609/117423fec367466abbeaca466dffcae2.jpg)
![](https://image.cha138.com/20210609/712c99c325324ff088be55dc9fc95384.jpg)
这里存在的问题是需要遍历整棵树才知道某个结点的双亲。
改进
双亲孩子表示法
![](https://image.cha138.com/20210609/1c2e6498b89f44a99985fbb43905b095.jpg)
孩子兄弟表示法
任意一棵树,它的结点的第一个孩子如果存在就是唯一的,它的右兄弟如果存在也是唯一的。因此,我们设置两个指针,分别指向该结点的第一个孩子和此结点的有兄弟。
![](https://image.cha138.com/20210609/472da8bbbba84edf87cf59195f4d3a00.jpg)
![](https://image.cha138.com/20210609/78a919d6583b4d1587546ebd73789814.jpg)
所有有必要知道父结点,完全可以再增加一个parent指针域来解决快速查找双亲的问题。
其实这个表示法的最大好处是它把一棵复杂的树变成了一棵二叉树。
![](https://image.cha138.com/20210609/23633d0c3f3549a6a8f3035d651698c6.jpg)
以上是关于《大话数据结构》笔记(6-1)--树:树的主要内容,如果未能解决你的问题,请参考以下文章