/*
名称:二叉树线索化
说明:这个东西,一开始弄起来,我去,感觉老复杂了。照着书上看了好久,愣是没看懂,照着敲了一遍,又手动模拟推了一遍,有了一点思路。照着把后序的线索化和遍历也敲出来了。
这里要注意的是:对于中序来说,其能线索化后访问到其前驱和后继(可以理解为不通过栈访问到),而对于后序来说,其只能不通过栈访问到其后继(这也是我后序遍历敲的是倒序的原因),要想访问到其后继只能通过一般的递归或使用栈的方法。同理,先序遍历也只能访问到其后继。
*/
//线索化结点
typedef struct ThreadNode
{
int data;
ThreadNode *lchild,*rchild;
int ltag,rtag;
}ThreadNode,*ThreadTree;
//创建二叉树(未线索化)
void CreateThreadTree(ThreadTree &T)
{
int val;
cin>>val;
if(val == -1)
{
T = NULL;
}
else
{
T = new ThreadNode;
T->data = val;
T->ltag = 0;
T->rchild = 0;
CreateThreadTree(T->lchild);
CreateThreadTree(T->rchild);
}
}
//中序线索化
void InThread(ThreadTree &p,ThreadTree &pre) //pre是先序结点,p是当前节点
{
if(p!=NULL)
{
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;
InThread(p->rchild,pre); //递归右子树
}
}
//递归遍历创建中序线索二叉树
void CreateInThread(ThreadTree T)
{
ThreadTree pre = NULL;
if(T!=NULL)
{
InThread(T,pre);
pre->rchild = NULL;
pre->rtag = 1;
}
}
//递归输出中序线索化二叉树
void ThreadInOrder(ThreadTree T)
{
if(T != NULL)
{
ThreadInOrder(T->lchild);
cout<<T->data<<" "<<T->ltag<<"--"<<T->rtag<<endl;
ThreadInOrder(T->rchild);
}
}
//求中序线索化后以p为根节点的树的中序线索化的第一个结点
//即以p为根节点的树的最左下角的结点
ThreadNode* FirstNode(ThreadNode *p)
{
while(p->ltag == 0)
p = p->lchild; //一直向左下角前进,知道p无左子树
return p;
}
//求中序线索化后p的后继节点
ThreadNode* NextNode(ThreadNode *p)
{
if(p->rtag == 1) //如果p无右子树的话,线索化后的p结点的右指针即指向其后继节点
return p->rchild;
else
{
p = FirstNode(p->rchild); //如果p有右子树的话,则以p右孩子为树的第一个结点就是其后继结点
return p;
}
}
//非递归中序遍历线索二叉树(不需要用到栈)
void ThreadInOrder1(ThreadNode *T)
{
for(ThreadNode *p = FirstNode(T);p != NULL;p = NextNode(p))
{
cout<<p->data<<" ";
}
}
//后序线索化
void PostThread(ThreadTree &p,ThreadTree &pre)
{
ThreadNode *q;
if(p != NULL)
{
PostThread(p->lchild,pre);
PostThread(p->rchild,pre);
if(p->lchild == NULL)
{
p->ltag = 1; //打上线索化标志
p->lchild = pre;
}
if(pre != NULL && pre->rchild != NULL) //pre指向上一次递归中的结点,即上一个结点
{
pre->rtag = 1; //打上线索化标志
pre->rchild = p;
}
pre = p;
}
}
//后序创建线索化二叉树
void CreatePostThread(ThreadTree T)
{
ThreadTree pre = NULL;
if(T != NULL)
{
PostThread(T,pre);
}
}
//求后序线索化后结点p的前驱结点
ThreadNode* PreNode(ThreadTree p)
{
if(p != NULL)
{
if(p->ltag == 1)
return p->lchild;
else
{
if(p->rchild != NULL)
return p->rchild;
else
return p->lchild;
}
}
}
//后序遍历二叉树(倒序遍历非递归)
void ThreadPostOrder2(ThreadTree T)
{
for(ThreadNode *p = T; p != NULL;p = PreNode(p))
{
cout<<p->data<<" ";
}
}