王道C语言C++版线索二叉树可运行总结--树3

本文介绍了线索二叉树的概念,包括其链式存储结构和左右线索的含义。通过先根序列创建二叉树,并实现中序线索化,使得二叉树支持中序遍历。同时提供了中序遍历和获取中序序列第一个及后续结点的函数,展示了线索二叉树的中序遍历过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

王道源码运行结果如下

//线索二叉树的链式存储结构
/

左前右后
ltag :0 lchild域指向结点的左孩子
:1 lchild域指向结点的前驱
rtag :0 rchild域指向结点的右孩子
:1 rchild域指向结点的后继
/

#include<cstdio>
#include<cstdlib>

//线索二叉树的链式存储结构
/*
    左前右后
    ltag :0 lchild域指向结点的左孩子
         :1 lchild域指向结点的前驱
    rtag :0 rchild域指向结点的右孩子
         :1 rchild域指向结点的后继
*/
typedef struct TreadNode{
    char data;
    struct TreadNode *lchild, *rchild;
    int ltag, rtag;
}ThreadNode, *ThreadTree;

void InitThreadTree(ThreadTree &bt){
    bt = (ThreadTree)malloc(sizeof(ThreadNode));
    bt->lchild = bt->rchild = NULL;
    bt->ltag = bt->rtag = 0;
}
//按照先根序列创建一棵二叉树
const char *str = "12040035000";
void CreateThreadTree(ThreadTree &bt){
    //printf("%s\n", str);
    int ch = str[0];
    str++;
    if(ch == '0')
        bt = NULL;
    else{
        bt = (ThreadNode*)malloc(sizeof(ThreadNode));
        bt->data = ch;
        bt->lchild = bt->rchild = NULL;
        bt->ltag = bt->rtag = 0;
        CreateThreadTree(bt->lchild);
        CreateThreadTree(bt->rchild);
    }
}

/*线索二叉树的构造,即二叉树的线索化,实质上就是遍历一遍二叉树,
发现该结点的左右指针域是否为空,若为空,分别将其改造成指向前驱和后继结点即可,
不要忘记改变标志位的状态*/
void InThread(ThreadTree &p, ThreadTree &pre){
    if(p != NULL){
        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);//递归线索化右子树
    }
}
//通过中序遍历建立中序线索二叉树的主过程如下
void CreateInThread(ThreadTree &T){
    ThreadTree pre = NULL;
    //借助一个pre指针指向中序遍历时上一个刚刚访问过的结点,表示各节点的前后关系
    if(T != NULL){
        InThread(T, pre);
        pre->rchild = NULL;//处理遍历的最后一个结点
        pre->rtag = 1;
    }
}
//二叉树的中序遍历算法
void InOrderTraverse(ThreadTree bt){
    if(bt != NULL){
        InOrderTraverse(bt->lchild);
        printf("%c", bt->data);
        InOrderTraverse(bt->rchild);
    }
}
//求中序线索二叉树中中序序列下的第一个结点
ThreadNode* Firstnode(ThreadNode *p){
    while(p->ltag == 0)//记得创建结点时,tag初始化为0,不然找不到中序第一个结点
        p = p->lchild;//最左下结点(不一定是叶子结点)

    return p;
}
//求中序线索二叉树中结点p在中序序列下的后继结点
ThreadNode* Nextnode(ThreadNode *p){
    if(p->rtag == 0)    return Firstnode(p->rchild);//rtag == 0,右孩子存在,返回其右子树的第一个结点
    else return p->rchild;//rtag == 1,直接返回其右孩子指针指向的后继结点
}
//不含头结点的中序线索二叉树的中序遍历算法
void Inorder(ThreadNode *T){
    for(ThreadNode *p = Firstnode(T); p != NULL; p = Nextnode(p))
        printf("%c", p->data);//记得创建结点时,tag初始化为0,不然找不到中序第一个结点
}
int main()
{
    /*
                1
             /    \
           2       3
          / \     / \
         0  4    5  0
           / \  / \
          0  0 0  0
   */
    //对于形如上图的二叉树线索化
    ThreadTree bt;
    InitThreadTree(bt);
    //char str[] = "12040035000";//先序次序,声明在前面的全局变量
    CreateThreadTree(bt);
    puts("二叉树中序遍历:");
    InOrderTraverse(bt);puts("");

    CreateInThread(bt);
    puts("线索二叉树中序遍历:");
    Inorder(bt);puts("");
    /*
    二叉树中序遍历:
    24153
    线索二叉树中序遍历:
    24153
    */
    return 0;
}