线索二叉树

线索二叉树考的不多

目录

基础代码

增设头结点并线索化的代码实现

中序遍历已经线索化的二叉树


手工部分的话不难,我这里放大佬博客了

图解线索二叉树_八百万的博客-CSDN博客_后序线索二叉树画法图解

 很快就能理解并写出线索二叉树的手工题

直接上

基础代码

#define OK            1
#define ERROR         0
#define OVERFLOW     -1

typedef int Status;

typedef char TElemType;                     
 
typedef enum { Link, Thread } PointerTag;       //Link==0,表示指向左右孩子指针
                                                //Thread==1,表示指向前驱或后继的线索
//二叉树线索结点存储结构
typedef struct BiThrNode {
  TElemType data;                       //结点数据
  struct BiThrNode *lchild, *rchild;    //左右孩子指针
  PointerTag LTag;                      
  PointerTag RTag;                      //左右标志
}BiThrNode, *BiThrTree;


//具体线索二叉树的函数实现!
void InThreading(BiThrTree B,BiThrTree *pre) {
  if(!B) return;
 
  InThreading(B->lchild,pre);   
//--------------------中间为修改空指针代码---------------------
 
  if(!B->lchild){                   //没有左孩子 
    B->LTag = Thread;               //修改标志域为前驱线索
    B->lchild = *pre;               //左孩子指向前驱结点
  }
 
  if(!(*pre)->rchild){              //没有右孩子
    (*pre)->RTag = Thread;          //修改标志域为后继线索
    (*pre)->rchild = B;             //前驱右孩子指向当前结点
  }
 
  *pre = B;                         //保持pre指向p的前驱
//---------------------------------------------------------
  InThreading(B->rchild,pre);
}

 

增设头结点
线索化后的二叉树,就如同操作一个双向链表。于是我们想到为二叉树增设一个头结点,这样就和双向链表一样,即能够从第一个结点正向开始遍历,也可以从最后一个结点逆向遍历。

在线索二叉链表上添加一个head结点,并令其lchild域的指针指向二叉树的根结点(A),其rchild域的指针指向中序遍历访问的最后一个结点(G)。同样地,二叉树中序序列的第一个结点中,lchild域指针指向头结点,中序序列的最后一个结点rchild域指针也指向头结点。

于是从头结点开始,我们既可以从第一个结点顺后继结点遍历,也可以从最后一个结点起顺前驱遍历。就和双链表一样。

增设头结点并线索化的代码实现

//为线索二叉树添加头结点,使之可以双向操作
Status InOrderThreading(BiThrTree *Thrt,BiThrTree T){
  if(!(*Thrt = (BiThrTree)malloc(sizeof(BiThrNode)))) 
                    exit(OVERFLOW);  //开辟结点
  (*Thrt)->LTag = Link;         
  (*Thrt)->RTag = Thread;               //设置标志域
  (*Thrt)->rchild = (*Thrt);            //右结点指向本身
 
 if(!T) {
    (*Thrt)->lchild = (*Thrt);
    return OK;       //若根结点不存在,则该二叉树为空,让该头结点指向自身.
  }

  BiThrTree pre;                //设置前驱结点
                                //令头结点的左指针指向根结点
  pre = (*Thrt);
  (*Thrt)->lchild = T;
                          //开始递归输入线索化
  InThreading(T,&pre);
  //此时结束了最后一个结点的线索化了,下面的代码把头结点的后继指向了最后一个结点.
  //并把最后一个结点的后继也指向头结点,此时树成为了一个类似双向链表的循环.
  pre->rchild = *Thrt;
  pre->RTag = Thread;
  (*Thrt)->rchild = pre;
  return OK;
}

中序遍历已经线索化的二叉树

代码实现

Status InOrderTraverse_Thr( BiThrTree Thrt, Status (*Visit)(TElemType e)){
    BiThrTree p;
    p = Thrt->lchild;
    while(p != Thrt){
        while(p->LTag == Link)
            p = p->lchild; //先走到最左端,开始
        if(!(*Visit)(p->data))
            return ERROR;
        while(p->RTag == Thread && p != Thrt){
            p = p->rchild;// 如果右指针是个线索,直接向后遍历后继
            (*Visit)(p->data);
        }
        if (p != Thrt)
                 /* 如果不加区分就走向右子树,很有可能出现死循环,因为p刚刚停到Thrt
                    还没进行下一次循环判断,就立刻指向Thrt的后继,循环可能不会终止*/
            p = p->rchild;
    }
return OK;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值