线索二叉树

我们知道,一颗二叉树不总是有两颗子树,也就是存在左子树或右子树为空的情况,这样就造成了存储空间的浪费,利用这些空链域来存放结点的前驱和后继的信息,就可以保存在遍历过程中的前驱和后继信息了。

这是一颗二叉树

我们要将其线索化并用中序遍历的方法输出,按照中序遍历的顺序:先遍历左子树,再遍历根结点,最后遍历右子树,那么,其输出结果应该为:CBDAEF

线索二叉树的结构

线索二叉树的结点结构
用代码表示为

typedef enum{Link,Thread} Pointag;
//Link = 0表示指向左右孩子指针,Thread = 1表示指向前驱或后继的线索

typedef struct BiThNode
{
    ElemType data;
    struct BiThNode *lchild,*rchild;
    Pointag ltag,rtag;          //左右线索标志
}BiThNode,*BiThTree;

创建线索二叉树


//创建一颗线索二叉树
void CreateBiThTree(BiThTree *T)
{
    char c;

    scanf("%c",&c);
    if(' ' == c)
    {
        *T = NULL;
    }
    else
    {
        *T = (BiThTree)malloc(sizeof(BiThNode));
        (*T)->data = c;
        (*T)->ltag = (*T)->rtag = Link;                  //默认存在左子树和右子树
        CreateBiThTree(&(*T)->lchild);
        CreateBiThTree(&(*T)->rchild);
    }
}

中序遍历实现

//采用中序遍历
void InTraverse(BiThTree T)
{
    if(T)
    {
        InTraverse(T->lchild);
        if(!T->lchild)                  
        { 
            T->ltag = Thread;
 //如果没有左孩子,则让左子树指针指向前一个访问的结点
        }
        if(!Pre->rchild)                   
        {
            Pre->rtag = Thread;
            Pre->rchild = T;                 
 //前驱右孩子指针指向后继(当前结点T)
        }

        Pre = T;                            //记下当前结点
        InTraverse(T->rchild);
    }
}

Pre指针指向上一次访问的结点,在使用之前需初始化

void InOrderThreading(BiThTree *p,BiThTree T)
{
  *p = (BiThTree)malloc(sizeof(BiThNode));
  (*p)->ltag = Link;
  (*p)->rtag = Thread;
  (*p)->rchild = *p;

  if(!T)                 //如果树为空
  {
     (*p)->lchild = *p; 
  }
  else
  {
      (*p)->lchild = T;            //p左子树指针指向根结点
      Pre = *p;                    //初始时Pre指向根结点
      InTraverse(T);
      Pre->rchild = *p;
      Pre->rtag = Thread;
      (*p)->rchild = Pre; 
  }
}

//中序遍历,非递归

void InOrderTraversing(BiThTree T)
{
  BiThTree p;
  p = T->lchild;                               //p指向根接结点
  while(p != T)                                //空树或遍历结束时 p == T
  {
      while(p->ltag == Link)                        //遍历左子树
      {
          p = p->lchild;
      }
      visit(p->data);                        //访问结点数据
      while( p->rtag == Thread && p->rchild != T)
      {
          p = p->rchild;
          visit(p->data);
      }
      p = p->rchild;
  } 
}

完整代码

#include <stdio.h>
#include<stdlib.h>

typedef enum{Link,Thread} Pointag;//Link = 0表示指向左右孩子指针,Thread = 1表示指向前驱或后继的线索
typedef char ElemType;

typedef struct BiThNode
{
    ElemType data;
    struct BiThNode *lchild,*rchild;
    Pointag ltag,rtag;
}BiThNode,*BiThTree;

BiThTree Pre;              //定义一个全局变量作为节点的前驱指针

//创建一颗线索二叉树
void CreateBiThTree(BiThTree *T)
{
    char c;

    scanf("%c",&c);
    if(' ' == c)
    {
        *T = NULL;
    }
    else
    {
        *T = (BiThTree)malloc(sizeof(BiThNode));
        (*T)->data = c;
        (*T)->ltag = (*T)->rtag = Link;                  //默认存左子树和右子树
        CreateBiThTree(&(*T)->lchild);
        CreateBiThTree(&(*T)->rchild);
    }
}

//访问数结点
void visit(char c)
{
  printf("%c ",c);
}

//采用中序遍历
void InTraverse(BiThTree T)
{
    if(T)
    {
        InTraverse(T->lchild);
        if(!T->lchild)                  
        { 
            T->ltag = Thread;
            T->lchild = Pre;                //如果没有左孩子,则让左子树指针指向前一个访问的结点
        }
        if(!Pre->rchild)                   
        {
            Pre->rtag = Thread;
            Pre->rchild = T;                  //前驱右孩子指针指向后继(当前结点T)
        }

        Pre = T;                          //记下当前结点
        InTraverse(T->rchild);
    }
}

//设置Pre指针
void InOrderThreading(BiThTree *p,BiThTree T)
{
  *p = (BiThTree)malloc(sizeof(BiThNode));
  (*p)->ltag = Link;
  (*p)->rtag = Thread;
  (*p)->rchild = *p;

  if(!T)                 //如果树为空
  {
     (*p)->lchild = *p; 
  }
  else
  {
      (*p)->lchild = T;
      Pre = *p;
      InTraverse(T);
      Pre->rchild = *p;
      Pre->rtag = Thread;
      (*p)->rchild = Pre; 
  }
}

//中序遍历,非递归
void InOrderTraversing(BiThTree T)
{
  BiThTree p;
  p = T->lchild;                               //p指向根接结点
  while(p != T)                                //空树或遍历结束时 p == T
  {
      while(p->ltag == Link)                        //遍历左子树
      {
          p = p->lchild;
      }
      visit(p->data);                        //访问结点数据
      while( p->rtag == Thread && p->rchild != T)
      {
          p = p->rchild;
          visit(p->data);
      }
      p = p->rchild;
  } 
}

int main()
{
    BiThTree P,T = NULL;

    CreateBiThTree(&T);

    InOrderThreading(&P,T);

    printf("中序输出结果为:");

    InOrderTraversing(P);

    printf("\n");

    return 0;
}

输入:ABC_ _ D _ _ E _ F _ _ ( _ 代表空格 )
输出结果为:
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值