线索二叉树的实现(C语言)

概念

鉴于普通二叉树使用过程中会出现空间的浪费,后人对在在二叉树的的基础上做了改进,利用它的空指针域存放在某种遍历次序下指向它的前驱结点,和后继结点的指针。这些指针称为线索,相应的二叉树就成了线索二叉树。
结点结构
这里写图片描述

  • Ltag为0时指向该结点的左孩子,为1时指向该结点的前驱。
  • Rtag为0时指向该结点的右孩子,为1时指向该结点的后继。

结构实现

线索存储结构定义

typedef enum {Link,Thread} PointerTag;    //定义线索
typedef struct BithrNode{
    char data;                                //结点数据
    struct BithrNode *pLchild;        
    struct BithrNode *pRchild;                //左右孩子
    PointerTag Ltag;
    PointerTag Rtag;                          //左右标志
}BiThrNode,*BiThrTree;

树的线索化
树的线索化过程其实就是遍历过程中修改空指针域,因为此时当前结点的后继还没有访问到,只能对它的前驱结点进行判断,所以用一个全局变量来存储该结点的前驱结点,完成后续结点线索化。

BiThrTree pre;   //定义全局变量,保存前驱结点

中序遍历线索化过程

void InThreading(BiThrTree T)
{
     if( T )                        //判断根结点是否为空
    {                            
        InThreading(T->pLchild);   //递归左子树线索
        if (!T->pLchild)           //左子树为空
        {                            
             T->Ltag = Thread;    //前驱线索
            T->pLchild = pre;    //左子树保存前驱结点
         }
        if(!pre->pRchild)          //右孩子为空
        {
            pre->Rtag = Thread;    //后继线索
            pre->pRchild = T;      //右子树指向后继
        }
           pre = T;                   //保持pre指向T的前驱
           InThreading(T->pRchild);   //递归右子树线索化
        }
          return;
}    

为了和双向链表一样,从根结点或者是尾结点都能访问整个树当中的数据,我们可以定义一个头结点,(a)让头结点的左指针域指向根结点,(b)右指针域指向中序遍历的最后一个结点。(c)让中序遍历的第一个结点的左指针域指向头结点,(d)最后一个结点的右指针域指向头结点。
这里写图片描述
代码如下

  • 其中p是头指针,t是根结点
void InOrdThreading(BiThrTree *p,BiThrTree t)
{
     *p = (BiThrTree)malloc(sizeof(BiThrNode)); //为头结点分配空间
      if((*p) == NULL)
      {
        printf("内存分配失败\n");
        exit(1);
      }
        (*p)->Ltag = Link;            
        (*p)->Rtag = Thread;          //后继线索线索
        (*p)->pRchild = *p;           //右指针域先指向自身
        if(!t)                        //判断根结点是否为空
            (*p)->pLchild = *p;       //为空头结点左指针域指向自身
        else{
                (*p)->pLchild = t;     //不空指向根结点
                pre = *p;              //初始化前驱结点
                InThreading(t);        //线索化过程
                pre->pRchild = *p;     //完成(b)过程
                pre->Rtag = Thread;    //后继线索化
                (*p)->pRchild = pre;   //完成(d)过程
        }
        return;
 }

遍历输出


  • 其中p是头结点,T是根结点
void InOrderTraverse(BiThrTree p)
{
        BiThrTree T;                
        T = p->pLchild;                                     
        while( p!=T)                  //空树或者遍历结束时
        {
            while(T->Ltag == Link)  // 当Link等于0时循环到中序序列第一个结点
            T = T->pLchild;
            printf("%c\t",T->data);    //打印数据
            while(T->Rtag == Thread && T->pRchild != p) 
            {
                T = T->pRchild;
                printf("%c\t",T->data);
            }
            T = T->pRchild;       //T递进至右子树根
    }
    printf("\n");
    return;
}         

  • 输入

  • 输出
    这里写图片描述
    树的建立采用前序遍历递归的方式创建,本篇文章不再赘述。
    有问题欢迎指正。

猜你喜欢

转载自blog.csdn.net/Cxinsect/article/details/81370158