一、树的存储结构(孩子兄弟表示法)
思想:
以二叉链表作为树的存储结构,链表中每个结点设有两个链域,分别指向该结点的第一个孩子结点和
下一个兄弟(右兄弟)结点。
存储结构:
typedef struct CSNode
{
DataType data;
struct CSNode *FirstChild;
struct CSNode *Nextsibling;
}CSNode,*CSTree ;
二、树、森林与二叉树的相互转换
(1)树转换为二叉树
约定树中每一个结点的孩子结点按从左到右的次序编号,即把树作为有序树看待。
思想:
对于树中的任一结点,将其第一个孩子结点作为转化的二叉树的左孩子结点,将其右兄弟结点作为转化的
二叉树右孩子结点。
方法:
***树中所有相邻兄弟之间加一条连线
***对树中的每个结点,只保留其与第一个孩子结点之间的连线,删去其与其他孩子结点之间的连线。
***以树的根节点为轴心,将整棵树顺时针旋转一定的角度,使之结构层次分明。
注意:
经过转化所构成的二叉树是唯一的。
由树转化而成的二叉树,其根节点必然没有右孩子。
(2)森林转换为二叉树
方法:
***将森林中的每棵树转换成相应的二叉树
***第一棵二叉树不动,从第二棵二叉树开始,依次把后一棵二叉树的根结点作为前一棵二叉树根结点的右孩子,
当所有二叉树连在一起后,所得到的二叉树就是有森林转换得到的二叉树。
注意:
有森林转换而得到的二叉树,其根结点必定有右孩子。
(3)二叉树还原为树或森林
方法:
***若某结点是其双亲的左孩子,则把该结点的右孩子、右孩子的右孩子......都与该结点的双亲结点用线连起来
***删除原二叉树中所有双亲结点与右孩子结点的连线
***整理由前两步所得到的树或森林,使之结构层次分明
三、树与森林的遍历
(1)树的遍历
分类:
《1》先根遍历
***访问根结点
***从左到右,依次先根遍历根结点的每一棵子树
《2》后根遍历
***从左到右,依次后根遍历根结点的每一棵子树
***访问根结点
关系:
树的先根遍历《===========》转换后二叉树的先序遍历
树的后根遍历《===========》转换后二叉树的中序遍历
先根遍历:
void RootFirst(CSTree root)
{
if(root != NULL)
{
visit(root->data); //访问根结点
RootFirst(root->FirstChild); //先根遍历首子树
RootFirst(root->Nextsibling); //先根遍历兄弟树
}
}
后根遍历:
void RootAfter(CSTree root)
{
if(root != NULL)
{
RootAfter(root->FirstChild); //后根遍历首子树
RootAfter(root->Nextsibling); //后根遍历兄弟树0
visit(root->data); //访问根结点
}
}
(2)森林的遍历
分类:
《1》先序遍历
***访问森林中第一棵树的根结点
***先序遍历第一棵树的根结点的子树森林
***先序遍历除去第一棵树之后剩余的树构成的森林
《2》中序遍历
***中序遍历森林中第一棵树的根结点的子树森林
***访问第一棵树的根结点
***中序遍历除去第一棵树之后剩余的树构成的森林
《3》后序遍历
***后序遍历森林中第一棵树的根结点的子树森林
***后序遍历除去第一棵树之后剩余的树构成的森林
***访问第一棵树的根结点
关系:
森林的先序遍历《==========》转换后二叉树的先序遍历
森林的中序遍历《==========》转换后二叉树的中序遍历
森林的后序遍历《==========》转换后二叉树的后序遍历
注意:
森林的遍历算法可以采用其对应的二叉树的遍历算法来实现。