简述
二叉树的线索化就是对利用二叉树指向空的指针节点加以利用,以实现能快速找到二叉树的直接前驱和直接后继
使其指空的左孩子指针指向其前驱
使其指空的有孩子节点指向其后继
对于不同的遍历顺序线索化的方式都是相同的,只不过线索化的线索有所不同
这里的代码以使用最多的中序线索化为例,完成二叉树的线索化,及利用线索化二叉树进行遍历的操作
代码
带头结点的线索化
#include <bits/stdc++.h>
using namespace std;
typedef char Elemtype;
typedef struct BiNode
{
Elemtype data;
struct BiNode *lchild, *rchild;
bool ltag, rtag; //tag的值为0表示节点是孩子,值为1表示节点是前驱
} BiNode, *BiTree;
BiTree per; //全局变量,表示当前节点的直接前驱
void creattree(BiTree &T);
void InThreading(BiTree &p);
void InOrderThreading(BiTree &Thrt, BiTree &T);
void bialy(BiTree T);
int main()
{
BiTree T; //表示二叉树的根节点
BiTree Thrt; //表示二叉树的头节点
creattree(T);
InOrderThreading(Thrt,T);
bialy(Thrt);
return 0;
}
void bialy(BiTree T) //传过来的是二叉树的头结点,对于线索化的二叉树进行遍历
{
BiTree p = T->lchild; //将p指向根节点
while (p != T)
{
while (p->ltag == 0) //如果左节点表示的是孩子,则沿左孩子一路向下
p = p->lchild;
cout << p->data; //访问左子树为空的节点
while (p->rtag == 1 && p->rchild != T) //沿着线索访问其后继节点
{
p = p->rchild;
cout << p->data;
}
p = p->rchild; //转向右子树
}
}
void InOrderThreading(BiTree &Thrt, BiTree &T) //对于二叉树的中序线索化
{
Thrt = new BiNode; //建立头结点
Thrt->ltag = 0; //头结点有左孩子,如果树不空,其左孩子为树根
Thrt->rtag = 1; //头结点的右孩子指针为线索
Thrt->rchild = Thrt; //右孩子节点指向自己
if (!T) //如果树空,左孩子节点也指向自己
Thrt->lchild = Thrt;
else
{
Thrt->lchild = T; //树不空,头结点指向左孩子
per = Thrt;
InThreading(T); //对树根进行线索化,线索化结束后per为最右边的节点
//完成线索化中的头结点与最右边的节点的线索
per->rchild = Thrt;
per->rtag = 1;
Thrt->rchild = per;
}
}
void InThreading(BiTree &p) //对于以p为树根的树进行中序线索化
{
if (p)
{
InThreading(p->lchild); //递归处理左子树
if (!p->lchild) //给p加上左线索
{
p->ltag = 1;
p->lchild = per;
}
else
p->ltag = 0;
if (!per->rchild) //给per加上右线索
{
per->rtag = 1;
per->rchild = p;
}
else
per->rtag = 0;
per = p;
InThreading(p->rchild); //递归处理右子树
}
}
void creattree(BiTree &T)
{
Elemtype data;
cin >> data;
if (data == '@')
T = NULL;
else
{
T = new BiNode;
T->data = data;
T->rtag = T->ltag = 0; //初始化节点的左右指针都指向孩子
creattree(T->lchild);
creattree(T->rchild);
}
}