MyDS 前中后序线索二叉树的建立与遍历

怪不得教材上没有后序的线索二叉树的遍历代码,考研也不考,分类讨论🤮了。。其实vis打个标记会很简洁。。。硬是只用 ∗ p a r e n t *parent parent写了半天,应该没什么bug了。。。
二叉树还是不简单啊

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
// (int *p;)==(typedef int *Pint; Pint p;)
typedef struct TBTNode  *TBTree;
typedef struct TBTNode{
    int data;
    int lt,rt;
    struct TBTNode *lchild;
    struct TBTNode *rchild;
    struct TBTNode *parent; // 后续线索二叉树遍历时需要维护父亲

}TBTNode;

void InThread(TBTNode *p,TBTNode *&pre){ //中序
    if(p!=NULL){
        InThread(p->lchild,pre);
        if(p->lchild==NULL) p->lchild=pre,p->lt=1;
        if(pre!=NULL&&pre->rchild==NULL) pre->rchild=p,pre->rt=1;
        pre=p;
        InThread(p->rchild,pre);
    }
}
void InVisit(TBTree B){
    puts("InVisit");
    if(B!=NULL){
        TBTNode *p=B;
        while(p->lt==0) p=p->lchild;//走到最左下
        for(;p!=NULL;){
            printf("%d ",p->data);
            if(p->rt==1) p=p->rchild; //有线索(没右子树)跳线索,回到祖先
            else { //没线索(有右子树) ,访问右子树
                p=p->rchild; //走右子树
                while(p->lt==0) p=p->lchild;//先访问右子树的最左下
            }
        }
    }
    puts("");
}
void PreThread(TBTNode *p,TBTNode *&pre){ //前序
    if(p!=NULL){
        if(p->lchild==NULL) p->lchild=pre,p->lt=1;
        if(pre!=NULL&&pre->rchild==NULL) pre->rchild=p,pre->rt=1;
        pre=p;
        if(p->lt==0)PreThread(p->lchild,pre); //注意前序可能回溯回来的时候有线索了,不能走线索的路
        if(p->rt==0)PreThread(p->rchild,pre);
    }
}
void PreVisit(TBTree B){
    puts("PreVisit");
    if(B!=NULL){
        for(TBTNode *p=B;p!=NULL;){
            printf("%d ",p->data);
            if(p->rt==1) p=p->rchild; //右边有线索,没子树
            else{
                if(p->lt==0) p=p->lchild; //左边没线索有子树
                else p=p->rchild; // 左边有线索,但是右边一定有子树
            }
        }
    }
    puts("");
}
void PostThread(TBTNode *p,TBTNode *&pre){ //后序
    if(p!=NULL){
        PostThread(p->lchild,pre);
        PostThread(p->rchild,pre);
        if(p->lchild==NULL) p->lchild=pre,p->lt=1;
        if(pre!=NULL&&pre->rchild==NULL) pre->rchild=p,pre->rt=1;
        pre=p;
    }
}
void PostVisit(TBTree B){
    puts("PostVisit");
    if(B!=NULL){
        TBTNode *p=B;
        while(p->lt==0||p->rt==0){//走到最下面
            if(p->lt==0) p=p->lchild;//优先走左边
            else p=p->rchild;
        }
        for(;p!=NULL;){
            printf("%d ",p->data);
            if(p->rt==1) p=p->rchild; //右边有线索,没子树
            else { //没线索(有右子树)
                TBTNode *q=p->parent;
                if(q==NULL) break; // p到根了
                if(q->lt==0&&q->lchild==p){ // p是q的左儿子
                    if(q->rt==0){ //右边有子树访问右边
                        q=q->rchild;
                        p=q;
                        while(p->lt==0||p->rt==0){//走到最下面
                            if(p->lt==0) p=p->lchild;//优先走左边
                            else p=p->rchild;
                        }
                    }
                    else {
                        p=p->parent; //到父亲肯定可以被线索
                    }
                }
                else { //p是q的右儿子
                    p=p->parent;
                    printf("%d ",p->data);
                    while(p!=NULL){
                        p=p->parent;
                        if(p==NULL) break;
                        if(q->rt==0){ //走到有右儿子的,否则一直走
                            p=p->rchild;
                            while(p->lt==0||p->rt==0){//走到最下面
                                if(p->lt==0) p=p->lchild;//优先走左边
                                else p=p->rchild;
                            }
                            break;
                        }
                        printf("%d ",p->data);
                    }
                }
            }
        }
    }
    puts("");
}
void dfs(TBTNode *p,TBTNode *&pre){
    if(p!=NULL){
        p->parent=pre;
        if(p->lt==0)dfs(p->lchild,p);
        if(p->rt==0)dfs(p->rchild,p);
    }
}
TBTree buildTBT(){
    int x;scanf("%d",&x);
    TBTNode *b;
    b=NULL;
    if(x==-1) {
        return b;
    }
    b=(TBTNode*)malloc(sizeof(TBTNode));
    b->data=x;b->lt=0;b->rt=0;
    b->lchild=buildTBT();
    b->rchild=buildTBT();
    return b;
}
//1 3 7 10 -1 -1 -1 6 -1 11 -1 -1 5 -1 8 -1 -1
int main(){
  //  TBTNode *b=buildTBT();
   // TBTNode *b1=buildTBT();
    TBTNode *b2=buildTBT();
   // TBTNode *p=NULL;
   // TBTNode *p1=NULL;
    TBTNode *p2=NULL;
  //  InThread(b,p);p->rchild=NULL;p->rt=1;
  //  InVisit(b);
 //   PreThread(b1,p1);p1->rchild=NULL;p1->rt=1;
  //  PreVisit(b1);
    PostThread(b2,p2); //出来到根节点,不一定没有右儿子
    if(b2->rchild==NULL) b2->rt=1,b2->rchild=NULL;
    p2=NULL;
    dfs(b2,p2);
    PostVisit(b2);
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值