【数据结构】线索二叉树(中序、先序、后序线索二叉树)

文章介绍了线索二叉树的概念,重点讲述了如何通过在二叉链表中添加标志位实现中序、先序和后序线索化,以便快速查找节点的前驱和后继。每个部分都给出了对应的存储示意图和函数实现。
摘要由CSDN通过智能技术生成

4.线索二叉树

4.1 线索二叉树概念

  • 目的:为了快速查找结点的前驱和后继。

  • 原理推导:

    ∵ 空指针数量= 2 n 2 + n 1 2n_2+n_1 2n2+n1,又 n 0 = n 2 + 1 n_0=n_2+1 n0=n2+1

    n 0 + n 1 + n 2 + 1 = n + 1 n_0+n_1+n_2+1=n+1 n0+n1+n2+1=n+1,即空指针数量等于结点总数

    ∴ 可以利用空指针来存储该结点的前驱后继。

  • 方法:

    在结点结构中多加两个int型标志位ltagrtag

    标志位=0lchildrchild指针分别指向左右孩子;

    标志位=1lchildrchild指针分别指向前后驱。

  • 定义

    //在原二叉树链式存储的基础上,添加左右线索标志位
    typedef struct ThreadNode{
        ElemType data;
        struct ThreadNode *lchild,*rchild;
        int ltag,rtag;//左右线索标志位
    }ThreadNode,*ThreadTree;
    

4.2 中序线索二叉树

  • 二叉树线索化:

    将二叉链表中的空指针改为前后继指针。

    而前后继需要遍历二叉树后才能得到。

    因此 二叉树线索化实质是要遍历一次二叉树。

  • 存储示意图:

  • 代码

    //中序线索化
    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); //递归,线索化右子树
        }
    }
    
    //中序线索化二叉树T
    void CreateInThread(ThreadTree T){
        ThreadTree pre=NULL;
        //非空二叉树,线索化
        if(T!=NULL){
            InThread(T,pre);//线索化二叉树
            pre->rchild=NULL;//处理遍历的最后一个结点
            pre->rtag=1;
        }
    }
    

4.3 先序线索二叉树

  • 存储示意图

  • 代码

    //先序线索化
    void PreThread(ThreadTree p,ThreadTree &pre){
        //左子树为空,建立前驱线索
        if(p!=NULL){
            p->lchild=pre;
            p->ltag=1;
        }
        //建立前驱结点的后继线索
        if(pre!=NULL&&pre->rchild==NULL){
            pre->rchild=p;
            pre->rtag=1;
        }
        pre=p;
        if(p->ltag==0){
            PreThread(p->lchild,pre);
        }
        PreThread(p->rchild,pre);
    }
    
    //先序线索化二叉树T
    void CreatePreThread(TreadTree T){
        ThreadTree pre=NULL;
        if(T!=NULL){
            PreThread(T,pre);
            if(pre->rchild==NULL)
                pre->rtag=1;
        }
    }
    

4.4 后序线索二叉树

  • 存储示意图

    在这里插入图片描述

  • 代码

    //后序线索化
    void PostThread(ThreadTree p,ThreadTree &pre){
        if(p!=NULL){
            PostThread(p->lchild,pre);//递归,线索化左子树
            PostThread(p->rchild,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;
        }
    }
    //后序线索化二叉树T
    void CreatePostThread(ThreadTree T){
        ThreadTree pre=NULL;
        if(T!=NULL){
            PostThread(T,pre);
            if(pre->rchild==NULL)
                pre->rtag=1;
        }
    }
    
  • 7
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值