线索二叉树

对于一般的二叉树,若它有n个链表,必有n+1个空链域(也就是为NULL的指针,即空指针)。

线索二叉树充分利用了这空指针,使得节点可以在没有左孩子或右孩子时,使得左孩子指针指向节点前驱,右孩子指针指向节点后继。对于同一个节点,它的前驱和后继与遍历方式有关,举例说明:中序遍历时根节点的前驱是遍历左子树时最后访问到的节点,而在后序遍历时前驱可能是左孩子也可能是右孩子,二者显然是不同的,同一个节点的后继也类似,因遍历方式不同而不同。

以下是线索二叉树中序遍历的代码实现。

#include <stdio.h>
#define ElemType int

typedef struct BiTNode
{
    ElemType data;
    BiTNode *lchild, *rchild;
    int LTag, RTag;
} BiTNode, *BiTree;

void InsertElem(BiTree &T, ElemType e) //插入函数:对每一个结点找到其合适位置并插入
{
    if (!T) //找到空节点
    {
        T = new BiTNode;
        T->data = e;
        T->lchild = T->rchild = NULL;
    }
    else
    {
        if (T->data > e)
            InsertElem(T->lchild, e); //根据当前节点值与待插入值之间的大小关系,分别向左向右寻找
        else
            InsertElem(T->rchild, e);
    }
}

void Create(BiTree &T, int ElemNum) //构建二叉排序树
{
    for (int i = 0; i < ElemNum; i++)
    {
        ElemType Element;
        scanf("%d", &Element);
        InsertElem(T, Element); //插入每一个输入的值
    }
}

void InOrderTraverse1(BiTree T) //中序遍历的递归算法
{
    if (T)
    {
        InOrderTraverse1(T->lchild);
        printf("%d ", T->data);
        InOrderTraverse1(T->rchild);
    }
}

BiTree pre;

void InThreading(BiTree T) //对以T为根节点的子树进行中序线索化
{
    if (T)
    {
        InThreading(T->lchild); //对左子树线索化
        if (!T->lchild)         //T的左子树为空,左孩子指针指向前驱
        {
            T->LTag = 1;
            T->lchild = pre;
        }
        else
            T->LTag = 0;
        if (!pre->rchild) //pre的右子树为空,T成为pre的后继
        {
            pre->RTag = 1;
            pre->rchild = T;
        }
        else
            pre->RTag = 0;
        pre = T;                //保持pre为T的前驱
        InThreading(T->rchild); //对右子树线索化
    }
}

void InOrderThreading(BiTree &Thrt, BiTree T) //Thrt指向头结点
{
    Thrt = new BiTNode; //初始化一个头结点
    Thrt->LTag = 0;     //树非空时头结点的左孩子指针指向树的根节点
    Thrt->RTag = 1;     //头结点的右孩子指针线索化,指向自己
    Thrt->rchild = Thrt;
    if (!T)
    {
        Thrt->LTag = 1;
        Thrt->lchild = Thrt; //空树头结点的左指针指向自己
    }
    else
    {
        Thrt->lchild = T;
        pre = Thrt; //头结点所有值已完成初始化,将Thrt赋值给pre,作为一开始的前驱
        InThreading(T);
        pre->RTag = 1;
        pre->rchild = Thrt; //中序线索化函数调用完时,pre为最右节点
        Thrt->rchild = pre;
    }
}

void InOrderTraverse2(BiTree T) //中序遍历线索化的二叉树,传入参数为头结点
{
    BiTree p = T->lchild; //T为线索二叉树的头节点,p指向根节点
    while (p != T)
    {
        while (!p->LTag)
            p = p->lchild;
        printf("%d ", p->data);           //输出左子树为空的第一个节点:最“左下”的节点,这应当是中序遍历最先输出的点
        while (p->RTag && p->rchild != T) //依次访问后继节点并输出,直到最后一个节点
        {
            p = p->rchild;
            printf("%d ", p->data);
        }
        p = p->rchild; //回到头结点,结束循环
    }
}

int main()
{
    int ElemNum;
    scanf("%d", &ElemNum);
    BiTree T = NULL;
    Create(T, ElemNum);
    printf("递归形式的先序遍历:");
    InOrderTraverse1(T); //递归形式的中序遍历
    printf("\n--------------------------------------------------\n");
    BiTree Thrt;
    InOrderThreading(Thrt, T); //线索化二叉树
    printf("线索化后的先序遍历:");
    InOrderTraverse2(Thrt); //线索化后的中序遍历
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值