4.6线索化二叉树
(不用栈实现二叉树的非递归遍历)
note:
N个结点的二叉链表,每个结点都有指向左右孩子的结点指针,所以一共有2*N个指针,而N个结点的二叉树一共由N-1个分支,也就是说有N+1个空指针。
定义:对二叉树以某种次序遍历使其变为线索化二叉树的过程就叫做线索化。
在二叉链表的基础上增加两个标志位ltag和rtag。
typedef struct BiTNode{
ElemType data;
struct BiTNode *lchild, *rchild;
}BiTNode,*BiTreee; //二叉链表
typedef struct ThreadTNode{
ElemType data;
struct ThreadNode *lchild, *rchild;
int ltag,rtag; //线索链表
}ThreadTNode,*ThreadTree;
中序遍历对二叉树线索化的递归算法:
void InThread(ThreadTree &p,ThreadTree &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;
InThread(p->rchild,pre);
}
}
遍历线索化二叉树:
//求中序线索二叉树中中序序列的第一个结点
ThreadNode *Firstnode(ThreadNode *p){
while(p->ltag ==0)
p=p->lchild; //最左下结点
return p;
}
//求中序线索化二叉树结点p在中序序列下的后继结点
ThreadNode *NextNode(ThreadNode *p){
if(p->rtag==0)
return Firstnode(p->rchild);
else
return p->rchild; //rtag =1 直接返回
}
// 利用上面两个可以写出不含头结点的中序线索化二叉树得中序遍历算法
@1
void Inorder(ThreadNode *T){
for(ThreadNode *p =Firstnode(T);P!=NULL;p=Nextnode(p))
visit(p);
}
@2
void InOrderTraverse(ThreadTree T){
ThreadTree p=T;
while(p){
while(p->ltag == 0)
p=p->lchild;
printf("%c",p->data);
while(p->rtag ==1&&p->rchild ){
p=p->rchild;
printf("%c",p->data);
}
p=p->rchild;
}
}
//求中序线索二叉树中中序序列的最后一个结点
ThreadNode *lastnode(ThreadNode *p){
ThreadNode *p =Firstnode(T);
while(p!=NULL)
p=Nextnode(p);
return p;
}
//求中序线索化二叉树结点p在中序序列下的前驱结点
ThreadNode *NextNode(ThreadNode *p){
if(p->ltag==0)
return Firstnode(p->lchild);
else
return p->lchild; //ltag =1 直接返回
}