树与森林
一.树的储存结构
在大量的应用中,人们用过多种形式的存储结构来表示树。现在会详细的讲述三种储存结构,并详细研究其中最优秀
的一种储存结构。
1.双亲表示法
我们通过一个顺序表来存储这个树,表内的内容有:树本身的内容和它双亲的顺序表下标。它的根结点的双亲下标为-1
即可。
如果我们要求根结点,那么只需要重复取某个结点的双亲下标即可。
不过缺点很明显,求某个结点的时候,可能需要遍历整个顺序表。
2.孩子表示法
在孩子表示法中,我们通过类似于广义表的方式来存储,一个结点除了它本身的值,还会存所有儿子的根结点。这种方式会造成大量的空链域。或者在儿子结点中,我们再多存一个结点的度,这样可以节约末尾的空链域。
当然,我们还能想出一种更优化的方法。用一个单链表将所有结点线性的存起来,如果该结点有孩子(们),那么就把他们的下标串成链表给赋值给该结点。这样就很容易遍历孩子了,但很难知道它的双亲。如果我们再加上双亲表示法的方法,那么这棵树就比较完美了。
3.孩子兄弟表示法
我们构建一棵二叉树,树的左儿子表示它的儿子结点,树的右儿子表示它的兄弟结点。这种方式很容易遍历结点的儿子,如果再给他加一个双亲域,那也很容易进行向上遍历。
鉴于这种方式层次分明,便于操作,所以我们会着重研究这种方法。
二.兄弟孩子森林的操作
1.森林转换成二叉树
假设我们将一颗森林F={T1,T2,T3……Tm}转换成一颗二叉树B=(root,LB,RB)。
- 若F为空,则m=0.
- 若F不为空,则B的LB为T1展开的树,二RB则是按照2这条方式递归展开树{T2,T3……Tm}
2.二叉树转换成森林
同理
- 若B为空,那就为空。
- 否则,T1是由LB递归生成,T2由RB及其LB构成,T3由RB的RB及其LB构成。这样递归展开。
3.兄弟孩子森林的遍历
根据定义,我们可以先序遍历森林和中序遍历森林。而且遍历方式和二叉树很相似。
a.先序遍历(其实是DFS哦)
在先序遍历的时候:
- 访问根结点
- 先序遍历第一棵树的根结点的子树森林(就是遍历左儿子)
- 先序遍历出去第一棵树后剩余的森林(就是把右儿子当根结点重复2)
- 对上图遍历得
ABCDEFGHIJ
b.后序遍历
- 中序遍历森林中,第一棵树的根结点
- 访问第一棵树的根结点
- 中序遍历出去第一棵树之后剩余的树构成的森林
- 对上图遍历得
BCDAFEHJIG
4.说明
对于这部分呢,由于树不是二叉树,我们着重掌握它的三种存储方式和孩子兄弟法的两种遍历和树与森林的转化与还原即可。
至于代码的话,其实要写,写一个二叉森林的存储还行。否则代码量还是有点小大,就不着重介绍惹。