数据结构-二叉树的转换

二叉树的转换
如果对树或森林采用链表存储并设定一定的规则,就可以用二叉树结构表示树和森林。这样,对树的操作实现就可以借助二叉树存储,利用二叉树上的操作来实现。
树的存储结构
在实际应用中,很多事物是不能直接用二叉树来描述的,而只能用树和森林来表示。
1.双亲表示法
双亲表示法是用一组连续的空间来存储树上的结点,同时在每个结点上附加一个指示器来指明其双亲结点所在的位置。
其类型定义如下。
# define MAX_TREE_SIZE 100
typedef struct
{
TElemType data;
int parent;
}PTNode;
typedef struct
{
PTNode nodes[MAX_TREE_SIZE];
int n;
}PTree;
在这种表中,每个结点(除根结点外)有且仅有一个双亲结点,通过parent域很容易查找到任何结点的双亲。但是,在查找孩子结点时则需要遍历整个表。为了使查找孩子结点更方便些,可以采取下面的存储结构。
2.孩子链表表示法
孩子链表表示法也是用一组连续的空间来存储树上的结点,同时在每个结点上附加一个指针指向由其孩子结点构成的单链表。其类型定义如下。
typedef struct CTNode
{
int child;
struct CTNode*next;
}CTNode,*ChildPtr;
typedef struct
{
TelemType data;
ChildPtr firstchild;
}CTBox;
typedef struct
{
CTBox nodes[MAX_TREE_SIZE];
int n;
}CTree;

在这种表示法中,找孩子结点比较容易,只要搜索firstchild指针指向的单链表即可。但要找某一结点的双亲结点就比较困难了,需要搜索所有的单链表。为了克服上述两种表示法的弊端,可以将两种表示法综合起来使用。
3.孩子双亲表示法
孩子双亲表示法也是用一组连续的空间来存储树上的结点,同时在每个结点上附加一个指示器来指示其双亲结点的位置,再附加一个指针指向其孩子结点构成的单链表。
法示意图,其类型定义如下。
typedef struct CTNode
{
int child;
struct CTNode*next;
}CTNode,*ChildPtr;
typedef struct
{
TelemType data;
int parent;
ChildPtr firstchild;
}PCNode;
typedef struct
{
PCNode nodes[MAX_TREE_SIZE];
int n;
}PCTree;
在这种表示法中,既能很快地找到每个结点的双亲结点,又能很快地找到每个结点的孩子结点。但这种方法是用空间的代价换来的时间效率,在具体应用中一定要根据不同的情况去选择较为适合的存储结构。
以上三种结构都是用顺序表的形式来表示树和森林,这很难转换成二叉树的存储形式,也就不能用二叉树中理论和结构来描述树和森林。
4.孩子兄弟表示法
孩子兄弟表示法是以二叉链表作为存储结构来表示树和森林的一种结构,其中每个结点的两个指针分别指向其第一个孩子结点和下一个兄弟结点。
typedef struct CSNode
{
TElemType data;
struct CSNode *firstchild,*nextsibling;
}CSNode,*CSTree;
这种结构有利于实现树和森林的各种操作。例如,找某个结点的第i个孩子结点,只要先沿着firstchild指针找到第一个孩子结点,然后再沿着该孩子结点的nextsibling指针走i-1步即可。若每个结点增加一个双亲指针域,则可以很快找到其双亲结点。此外,孩子兄弟链表实质上就是前述的二叉链表,只是解释不同而已,有关二叉树的大部分操作均可在这种结构上实现。因此,孩子兄弟链表也成为树、森林与二叉树之间的桥梁和纽带。

一般树转换为二叉树
1.一般树和二叉树的二叉链表存储结构比较
一般树是无序树,树中结点的各孩子的次序是无关紧要的;二叉树中结点的左、右孩子结点是有区别的。为避免发生混淆,约定树中每一个结点的孩子结点按从左到右的次序排列。如图6-23所示为一棵一般树,根结点A有B、C、D三个孩子,可以认为,结点B为A的长子,结点C为B的次弟,结点D为C的次弟。

2.将一般树转换为二叉树的方法
一般树的长子作为其父结点的左子树,把一般树的次弟作为其兄结点的右子树,即可以把一棵一般树转换为一棵二叉树。
整个转换可以分为如下三步。
(1)连线——链接树中所有相邻的亲兄弟结点之间连线。
(2)删线——保留父结点与长子结点的连线,打断父结点与非长子结点之间的连线。
(3)旋转——以根结点为轴心,将整棵树顺时针旋转一定的角度,使之层次分明。

由上面的转换可以得出以下结论。
(1)在转换产生的二叉树中,左分支上的各结点在原来的树中是父子关系,而右分支上的各结点在原来的树中则是兄弟关系。
(2)由于树的根结点无兄弟,所以转换后的二叉树的根结点必定无右子树。
(3)一棵树采用长子、兄弟表示法所建立的存储结构与它所对应的二叉树的二叉链表存储结构是完全相同的。
(4)一般树转换为二叉树以后,将使树的深度增加。

森林转换为二叉树
森林是若干棵树的集合。只要将森林中的每一棵树的根视为兄弟,而每一棵树又可以用二叉树表示,这样,森林也就可以用二叉树来表示了。
森林转换为二叉树的方法如下。
(1)将森林中的每一棵树转换成相应的二叉树。
(2)第一棵二叉树保持不动,从第二棵二叉树开始,依次把后一棵二叉树的根结点作为前一棵二叉树根结点的右子树,直到把最后一棵二叉树的根结点作为其前一棵二叉树的右子树为止。

二叉树转换为树和森林
树转换为二叉树以后,其根结点必定无右子树;而森林转换为二叉树以后,其根结点有右分支。显然这一转换过程是可逆的,即可以依据二叉树的根结点有无右子树,将一棵二叉树还原为树或森林。
其转换方法。
(1)若某结点是其父结点的左孩子结点,则把该结点的右孩子结点、右孩子结点的右孩子结点,直到最后一个右孩子结点都与该结点的父结点连起来。
(2)删除原二叉树中所有的父结点与右孩子结点的连线。
(3)整理(1)、(2)的结果,使之层次分明,显示出树或森林的形状。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值