《大话数据结构》上的,大家可以参考一下
题目描述
在遍历二叉树的过程中,是按照一定的规则将二叉树中的结点排列成一个线性序列,从而得到二叉树中结点的先序序列或中序序列或后序序列。但是,当以二叉链表作为存储结构时,只能找到结点的左右孩子信息,而不能直接得到结点在任意一个序列中的前驱和后继的信息,而这种信息只有在遍历的动态过程中才能够得到。
为了保存这种信息,就需要使用线索链表。其中指向结点的前驱和后继的指针,叫做线索。添加上线索的二叉树称之为线索二叉树。其结点定义如下:
下面给出按照中序遍历将二叉树中序线索化的算法:
在已经线索化的二叉线索树中,进行中序遍历的算法如下所示:
本题中,将会给出一个按照先序遍历得出的字符串,空格代表空的子节点,大写字母代表节点内容。请通过这个字符串建立二叉树,并按照题目描述中算法,中序遍历二叉树并中序线索化二叉树,之后中序遍历输出二叉线索树。
输入格式
输入只有一行,包含一个字符串S,用来建立二叉树。保证S为合法的二叉树先序遍历字符串,节点内容只有大写字母,且S的长度不超过100。
输出格式
共一行,包含一串字符,表示按中序遍历二叉线索树得出的节点内容,每个字母后输出一个空格。请注意行尾输出换行。
样例输入
<span style="color:#333333"><span style="color:#333333">ABC DE G F </span></span>
样例输出
<span style="color:#333333"><span style="color:#333333">C B E G D F A </span></span>
#include<stdio.h>
#include<stdlib.h>
typedef enum{link,thread} pointerflag;
typedef struct BiTree{
char c;
struct BiTree *lchild,*rchild;
pointerflag lflag;
pointerflag rflag;
}*bitree,BITNODE;
bitree pre=NULL;//pre是全局变量,始终指向前驱结点
void creattree(bitree *);//建立二叉树
void thread_(bitree*,bitree);//线索化之前的准备
void threading(bitree);//线索化
void ThreadTraverse(bitree);//中序遍历
int main(){
bitree head=NULL;//指向头结点
bitree t=NULL;//指向根节点
creattree(&t);//创建根节点
thread_(&head,t);//线索化
ThreadTraverse(head);//中序遍历
}
void creattree(bitree* t){
char c;
c=getchar();
if(c==' '){
(*t)=NULL;
}
else{
(*t)=(bitree)malloc(sizeof(BITNODE));
(*t)->c=c;
creattree(&(*t)->lchild);
creattree(&(*t)->rchild);
}
}
void thread_(bitree* head,bitree t){
(*head)=(bitree)malloc(sizeof(BITNODE));
(*head)->lflag=link;
(*head)->rflag=thread;
(*head)->rchild=(*head);//右指针回指
if(!t)
(*head)->lchild=*head;//左指针回指
else{
(*head)->lchild=t;//有根结点
pre=(*head);
threading(t);
pre->rchild=*head;
pre->rflag=thread;//最后一个结点线索化
(*head)->rchild=pre;
}
}
void threading(bitree t){//线索化
if(t){
threading(t->lchild);
if(!(t->lchild)){
t->lflag=thread;
t->lchild=pre;
}
else
t->lflag=link;
if(!(pre->rchild)){
pre->rflag=thread;
pre->rchild=t;
}
else
t->rflag=link;
pre=t;
threading(t->rchild);
}
}
void ThreadTraverse(bitree head){
bitree p=head->lchild;//根结点开始
while(p!=head){
while(p->lflag==link){//因为是中序遍历,所以先找最左的结点
p=p->lchild;
}
printf("%c ",p->c);
while(p->rflag==thread&&p->rchild!=head){
p=p->rchild;
printf("%c ",p->c);
}
p=p->rchild;//意味着有右孩子,那么,p将成为新的根结点
}
}