如何构造中序线索二叉树?
typedef struct TBTNode
{
int ltag,rtag;//ltag=0时lchild指向做孩子,ltag=1时lchild作为线索指向本节点的前驱
struct TBTNode *lchild;
struct TBTNode *rchild;
char data;
}
void createInThread(TBTNode *root)//通过中序遍历建立中序线索二叉树的主程序
{
TBTNode *pre=NULL;
if(root)
{
InThread(root,pre);//建立线索化的函数
pre->rchild=NULL;//把先序序列的最后一个结点处理了,它的右孩子一定为空
pre->rtag=1;
}
}
void InThread(TBTNode *p,TBTNode *&pre)
{
if(p)
{
InThread(p->lchild,pre);
if(p->lchild==NULL)//表明此节点的左指针为空,可以当作线索
{
p->lchild=pre;
p->ltag=1;
}
if(pre!=NULL&&pre->rchild==NULL)//表明此时的前驱节点存在且其右指针为空,可以当作线索
{
pre->rchild=p;
pre->rtag=1;
}
pre=p;//保证pre始终指向下次新访问的p节点的前驱
InThread(p->rchild,pre);
}
}
//说明,此程序的大致模版其实就是二叉树的中序递归遍历,只不过将输出节点的那部分代码(27-37)
//换成了建立线索的过程,这种过程就叫二叉树的线索化
//程序进行完25行后此时pre指向中序遍历的最后一个节点,此节点的右孩子一定为空(不为空的话程序不会结束,因为还要遍历它的右子树),也可以作为线索,但程序
//已经结束了,所以需要添加16-17行用来线索化中序遍历序列的最后一个节点
如何遍历中序线索二叉树?
思路如下:
1.首先遍历以p为根的中序线索二叉树中序序列中的第一个节点(First函数)
2.整个循环依次遍历某节点的后继节点(Next函数)
TBTNode *First(TBTNode * p)//辅助遍历函数1:找某棵树在中序序列下的第一个结点
{
while(p->ltag==0)//找到中序遍历序列的第一个节点
{
p=p->lchild;//最左下节点(不一定是叶子节点,有可能有右孩子)
}
return p;
}
TBTNode *Next(TBTNode *p)//辅助遍历函数2:找结点p的后继
{
if(p->rtag==0)//证明此节点的后继又是一棵树,这棵树的中序序列的第一个节点才是此节点的后继
return First(p->rchild);
else
return p->rchild;//有线索就直接可以找到此节点的后继
}
//将First和Next函数结合起来可得到中序线索二叉树的遍历算法如下
void Inorder(TBTNode *root)
{
TBTNode *p
for(p=First(root);p!=NULL;p=Next(p))
{
visit(p);
}
}
//总结:
//1.思考First函数后个人得出的一个结论—中序序列下的第一个节点一定是最靠左边的左子树为空的节点;中序序列下的最后一个节点一定是最靠右边的右子树为空的节点(天勤p157),倒过来说都不一定成立。
//2.思考Next函数后个人得到的一个结论—节点p在中序序列下的后继节点要么通过p的线索找到要么就是以它右子树为根的树中的中序序列下的第一个节点为其后继节点;节点p在中序序列下的前驱节点要么通过p的线索找到要么就是以它左子树为根的树中的中序序列下的最后一个节点为其前驱节点(天勤p157)。