c语言实现二叉树的线索化和线索二叉树的遍历

时构建线索二叉树的结构体

        线索二叉树比平常的二叉树多了一个ltag域和一个rtag域,他们的作用在后面遍历时会说

#include<stdio.h>
#include<stdlib.h>
typedef char datatype;
typedef struct btnode {
    datatype data;
    btnode* lchild;          //二叉树的左孩子指针域
    btnode* rchild;          //二叉树的右孩子指针域
    int LTag,RTag;           //左右Tag值
}btnode;
typedef struct binarytree {
    btnode* root;
}binarytree;

进行二叉树的线索化之前先建立一颗二叉树

构造空树的函数:

void nulltree(binarytree* bt) {
    bt->root = NULL;
}

建立一颗二叉树的函数;

btnode* newnode(btnode* node, datatype x) {     //给结点赋值函数
    node = (btnode*)malloc(sizeof(btnode));
    node->data = x;
    return node;
}
binarytree* maketree(binarytree* bt, datatype x, binarytree* lt, binarytree* rt) {
    bt->root = newnode(bt->root, x);             //给二叉树的根节点赋值
    bt->root->lchild = lt->root;
    bt->root->rchild = rt->root;
    return bt;
}

main函数中建立一颗正常的二叉树bt1

int main() {
    binarytree bt1, bt2, bt3, bt4, bt5;
    nulltree(&bt5);
    maketree(&bt4, 'D', &bt5, &bt5);
    maketree(&bt3, 'C', &bt4, &bt5);
    maketree(&bt2, 'B', &bt5, &bt5);
    maketree(&bt1, 'A', &bt2, &bt3);
   return 0;
}

现在进行二叉树的线索化,二叉树的线索化实质是二叉树的遍历。

左右tag域的作用:二叉树按照某种顺序遍历后得到的一个顺序结构,遍历后的结果中如果结点的左孩子为空,则把ltag置为1,同时该结点的lchild指向该结点的前驱,同理,结点的右孩子为空,则把rtag置为1,同时rchild指向该结点的的后继,若结点的左右孩子都不为空,则ltag=0,rtag=0,这里有两个特殊的结点,则是第一个结点和最后一个结点,若第一个结点的左孩子为空,则它的lchild可以指向一个NULL的前驱结点,若最后一个结点的右孩子为空,则它可以指向一个NULL的后继结点

例子:

bt1中序遍历结果为:BADC,B是遍历结果的第一个结点,B结点的左右孩子均为空,此时B结点有一个后继结点D,由于B结点是第一个结点,且B结点的左孩子为空,所以可以看作B结点也有一个前驱结点NULL结点,此时将B结点的ltag域置为1,同时B的lchild指针域指向NULL结点,B结点的rtag置为1,同时B的rchild指向他的后继结点A,A结点左右孩子均不为空,所以将A结点的左右tag值置为0,D结点的左右孩子均为空,遍历结果他有一个前驱结点A,所以他的ltag=1,lchild指向A结点,他还有一个后继结点C,所以他的rtag=1,rchild指向他的后继结点C,遍历结果的最后一个结点C左孩子不为空,但右孩子为空,所以他的ltag=0,rtag=1,rchild指向一个NULL的后继结点

以上的过程就是二叉树的线索化

btnode*pre=NULL;                               //设置一个全局变量pre
                                               //pre意义为当前结点的前驱结点,p为当前结点
void inthread(btnode*p){                       
    if(p){                                     //线索化左子树
        inthread(p->lchild);
        if(p->lchild==NULL){
            p->LTag=1;
            p->lchild=pre;
        }
        if(pre!=NULL&&pre->rchild==NULL){
            pre->RTag=1;
            pre->rchild=p;
        }
        pre=p;                              把当前结点赋值给pre
        inthread(p->rchild);                //线索化右子树
    }
}
void inthreadtree(binarytree*bt){            //二叉树的线索化函数            
    inthread(bt->root);
}

接下来是线索化二叉树的遍历:

        

void inordertree(binarytree*bt){
    btnode*p=bt->root;
    if(p){
       while(p->lchild){                            //遍历最左结点
           p=p->lchild;
       }                                             
       while(p->RTag==1){                    //根据线索RTag访问后继结点直到访问到根节点
           printf("%c",p->data);
           p=p->rchild;
       }
       printf("%c",p->data);                    //访问根节点
       while(p->rchild){
           p=p->rchild;
       }
       while(p->lchild&&p->lchild!=bt->root){   //访问右子树的最右结点的最左结点
           p=p->lchild;
       }
       while(p){
           printf("%c",p->data);        
           p=p->rchild;
       }
        printf("\n");
    }
}

main函数:

int main() {
    binarytree bt1, bt2, bt3, bt4, bt5;
    nulltree(&bt5);
    maketree(&bt4, 'D', &bt5, &bt5);
    maketree(&bt3, 'C', &bt4, &bt5);
    maketree(&bt2, 'B', &bt5, &bt5);
    maketree(&bt1, 'A', &bt2, &bt3);
    inthreadtree(&bt1);
    inordertree(&bt1);
    return 0;
}

源码在此:https://blog.csdn.net/hypnumberone/article/details/124233555

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值