树,森林 二叉树之间转化 原理
从树的孩子兄弟表示法和二叉树的二叉链表表示法可以看出,树的孩子兄弟表示法实质上是二叉树的二叉链表存储形式,第一个孩子指针和右兄弟指针分别相当于二叉链表的左孩子指针和右孩子指针。所以,从物理结构上看,树的孩子兄弟表示法和二叉树的二叉链表是相同的,只是解释不同而已,如图5-32所示。
以二叉链表作为媒介,可导出树和二叉树之间的一个对应关系。也就是说,给定一棵树,可以找到唯一的一棵二叉树与之对应。这样,对树的操作实现就可以借助二叉树存储,利用二叉树上的操作来实现。
将一棵树转换为二叉树的方法是:
⑴加线--树中所有相邻兄弟结点之间加一条连线;
⑵去线--对树中的每个结点,只保留它与第一个孩子结点之间的连线,删去它与其它孩子结点之间的连线;
⑶层次调整--以根结点为轴心,将树顺时针转动一定的角度,使之层次分明。
图5-33给出了树及其转换为二叉树的过程。
可以看出,在二叉树中,左分支上的各结点在原来的树中是父子关系,而右分支上的各结点在原来的树中是兄弟关系。由于树的根结点没有兄弟,所以转换后,二叉树的根结点的右子树必为空。
根据树与二叉树的转换关系以及树和二叉树遍历的操作定义可知,树的遍历序列与由树转化成的二叉树的遍历序列之间具有如下对应关系:
树的前序遍历二叉树的前序遍历
树的后序遍历二叉树的中序遍历
2.森林转换为二叉树
森林是若干棵树的集合,将森林中的每棵树转换为二叉树,再将每棵树的根结点视为兄弟,这样,森林也同样可以转换为二叉树。
森林转换为二叉树的方法如下:
⑴将森林中的每棵树转换成二叉树;
⑵从第二棵二叉树开始,依次把后一棵二叉树的根结点作为前一棵二叉树根结点的右孩子,当所有二叉树连起来后,此时所得到的二叉树就是由森林转换得到的二叉树。
图5-34给出了森林及其转换为二叉树的过程。
下面给出森林转换为二叉树的形式化描述。由于树是森林的特例,所以这里的描述包含了树的情况。
设F={T1,T2,…,Tm}是森林,则可按如下规则转换成一棵二叉树B=(root,LB,RB),其中,root是二叉树的根,LB和RB分别为root的左右子树:
⑴若F为空,即m=0,则B为空二叉树;
⑵若F非空,则B的根root即为森林中第一棵树的根;B的左子树LB是从T1中根结点的子树森林F1={T11,T12,…,T1k}转换而成的二叉树;B的右子树RB是从森林F '={T2,T3,…,Tm}转换而成的二叉树。
3.二叉树转换为树或森林
树和森林都可以转换为二叉树,二者不同的是树转换成的二叉树,其根结点无右子树,而森林转换后的二叉树,其根结点有右子树。显然这一转换过程是可逆的,即可以依据二叉树的根结点有无右子树,将一棵二叉树还原为树或森林,具体方法如下:
⑴加线--若某结点x是其双亲y的左孩子,则把结点x的右孩子、右孩子的右孩子、……,都与结点y用线连起来;
⑵去线--删去原二叉树中所有的双亲结点与右孩子结点的连线;
⑶层次调整--整理由⑴、⑵两步所得到的树或森林,使之层次分明。
图5-35给出了一棵二叉树还原为森林的过程。
二叉树转换为树或森林的形式化描述为:
如果B=(root,LB,RB)是一棵二叉树,其中,root是二叉树的根,LB和RB分别为root的左右子树,则可按如下规则转换成森林F={T1,T2,…,Tm}:
(1)若B为空,则F为空;
(2)若B非空,则森林中第一棵树T1的根即为B的根root;T1中根结点的子树森林是由B的左子树LB转换而成;F中除T1之外其余树组成的森林F '={T2,T3,…,Tm}是由B的右子树RB转换而成。
4. 森林的遍历
森林有两种遍历方法:前序(根)遍历和后序(根)遍历。
前序遍历森林即为前序遍历森林中的每一棵树,对于图5-33(a)所示的森林进行前序遍历,得到遍历序列为:A B C D E F G H I J。
后序遍历森林即为后序遍历森林中的每一棵树,对于图5-33(a)所示的森林进行后序遍历,得到遍历序列为:B A D E F C H J I G。