BiTNode *p;
BiTNode *pre = NULL;
BiTNode *final = NULL;
void InOrder(BiTree T){
if(T!=NULL){
InOrder(T->lchild);
visit(T);
InOrder(T->rchild);
}
}
void visit(BiTNode *q){
if(q==p)
final = pre;
else
pre = q;
}
一、中序线索化
ThreadNode *pre = NULL;
typedef struct ThreadNode{
ElemType data;
struct ThreadNode *lchild,*rchild;
int ltag,rtag;
}ThreadNode,* ThreadTree;
void CreatInThread(ThreadTree T){
pre = NULL;
if(T!=NULL){
InThread(T);
if(pre->rchild==NULL)
pre->rtag=1;
}
}
void InThread(ThreadTree T){
if(T!=NULL){
InThread(T->lchild);
visit(T);
InThread(T->rchild);
}
}
void visit(ThreadNode *q){
if(q->lchild==NULL){
q->lchild = pre;
q->ltag = 1;
}
if(pre!=NULL&&pre->rchild==NULL){
pre->rchild = q;
pre->rtag = 1;
}
pre = q;
}
【思考】处理完遍历的最后一个结点,为什么没有判断rchild是否为NULL?
【解】因为在中序遍历时访问完一个结点后,如果有右孩子,那就一定会去访问右孩子,所以可以断定,最后一个节点,必没有右孩子
二、先序线索化
ThreadNode *pre = NULL;
void CreatPreThread(ThreadTree T){
pre = NULL;
if(T!=NULL){
PreThread(T);
if(pre->rchild==NULL)
pre->rtag=1;
}
}
void PreThread(ThreadTree T){
if(T!=NULL){
visit(T);
if(T->ltag==0)
PreThread(T->lchild);
PreThread(T->rchild);
}
}
void visit(ThreadNode *q){
if(q->lchild==NULL){
q->lchild = pre;
q->ltag = 1;
}
if(pre!=NULL&&pre->rchild==NULL){
pre->rchild = q;
pre->rtag = 1;
}
pre = q;
}
三、后序线索化
ThreadNode *pre = NULL;
void CreatPostThread(ThreadTree T){
pre = NULL;
if(T!=NULL){
PostThread(T);
if(pre->rchild==NULL)
pre->rtag=1;
}
}
void PostThread(ThreadTree T){
if(T!=NULL){
PostThread(T->lchild);
PostThread(T->rchild);
visit(T);
}
}
void visit(ThreadNode *q){
if(q->lchild==NULL){
q->lchild = pre;
q->ltag = 1;
}
if(pre!=NULL&&pre->rchild==NULL){
pre->rchild = q;
pre->rtag = 1;
}
pre = q;
}
四、总结
【核心】
- 中序/先序/后序遍历算法的改造,当访问一个结点时,连接该结点与前驱结点的线索信息
- 用一个指针pre记录当前访问结点的前驱结点
【易错点】
- 最后一个结点的rchild、rtag的处理
- 先序线索化中,注意处理 “爱的魔力转圈圈问题” ,当ltag == 0 时,才能对左子树先序线索化
|