数据结构之线索二叉树

线索二叉树

  • 在二叉树的前、中、后序三种遍历出来的树的结点,将其每一种遍历出现的结果换个角度将其排列成一个线性序列,再细看,这些这些线性序列中的每一个元素(结点)都有且仅有一个前驱结点和后继结点。而且更重要的是二叉树的每个叶子结点的左右指针都是空的,是不是觉得不够节约,那么综合上述及其他因素,就有了线索二叉树。
  • 先看看原始的二叉树的图

在这里插入图片描述

  • 再来看看将上图线索化后的图(中序遍历版)

在这里插入图片描述

  • 讲一讲二叉树某个节点的前驱或者后继节点;比如上图二叉树中序遍历结果为 A B D E C F G ,将这七个节点排列成一个线性序列,那么如 B 的前驱是 A ,后继是 D ;以此类推。
  • 假如要得到某个节的前驱或者后继节点;我们只从普通二叉树(第一张图)中某个节点来获得它的前驱或后继,但是,普通二叉树遍历的每个节点是没有备注前驱和后继关系的,所以需要间接得到,也就是只能将整个二叉树遍历一遍才能得到需要的前驱或后继;此时线索二叉树就产生了(样例如图二),将普通二叉树线索化,也就是将二叉树的节点之间建立了前驱和后继关系。
  • 总的来说,根据线索二叉树来获得某个节点的前驱或后继节点,是易如反掌的事。

直接上代码(此线索二叉树是有头节点的)

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

typedef enum
{
    Link,
    Thread
}PointTag;  //Link=0 表示指向左右孩子指针 ; Thread=1 表示指向前驱或后继的线索
//Link=0 means pointing to the left and right child pointer
//Tread=1 means pointing to predecessor or successor

typedef char ElemType;

typedef struct BiThrTNode
{
    ElemType data;
    struct BiThrTNode *lchild;
    struct BiThrTNode *rchild;
    PointTag LTag;    //左右标志
    PointTag RTag;      //left and right sign
}BiThrTNode, *BiThrTree;

typedef BiThrTree SElemType;
typedef struct StackNode
{
    SElemType sdata;
    struct StackNode *next;
}StackNode, *LinkStackNode;
typedef struct
{
    LinkStackNode top;
}LinkStack;

LinkStack S;

void init_Stack(LinkStack *S)
{
    S->top = NULL;
}

void push_Stack(LinkStack *S, SElemType e)
{
    LinkStackNode sNew = (LinkStackNode)malloc(sizeof(StackNode));

    sNew->sdata = e;
    sNew->next = S->top;
    S->top = sNew;
}

void pop_Stack(LinkStack *S, SElemType &e)
{
    LinkStackNode p = S->top;
    if (p == NULL)
    {
        return;
    }
    e = p->sdata;
    S->top = p->next;
    free(p);
    p = NULL;
}

SElemType get_Top(LinkStack S)
{
    if (S.top != NULL)
    {
        return S.top->sdata;
    }
    else
    {
        return NULL;
    }
}

bool isEmpty(LinkStack S)
{
    if (S.top == NULL)
    {
        return true;
    }
    else
    {
        return false;
    }
}

void creat_Tree(BiThrTree &T)
{
    init_Stack(&S);
    ElemType node[100]={};
    scanf("%s", node);
    int len = strlen(node);
    BiThrTree tn1, tn2;
    bool flag;
    if (node[0] != '#')
    {
        tn1 = (BiThrTree)malloc(sizeof(BiThrTNode));
        tn1->data = node[0];
        tn1->lchild = tn1;
        tn1->LTag = Link;
        tn1->rchild = tn1;
        tn1->RTag = Link;
        T = tn1;
        int k = 0;
        push_Stack(&S, tn1);
        while (!isEmpty(S) && k != len - 1)
        {
            flag = false;
            if (node[++k] != '#')
            {
                tn2 = (BiThrTree)malloc(sizeof(BiThrTNode));
                tn2->data = node[k];
                tn2->lchild = tn2;
                tn2->LTag = Link;
                tn2->rchild = tn2;
                tn2->RTag = Link;
                flag = true;
            }
            else
            {
                tn2 = NULL;
            }

            tn1 = get_Top(S);
            while(tn1->lchild != tn1 && tn1->rchild != tn1)
            {
                pop_Stack(&S, tn1);
                tn1 = get_Top(S);
            }
            if (tn1->lchild == tn1)
            {
                tn1->lchild = tn2;
            }
            else
            {
                tn1->rchild = tn2;
            }

            if (flag)
            {
                push_Stack(&S, tn2);
            }
        }

    }
    else
    {
        T = NULL;
        printf("The tree is empty! The tree can`t created!\n");
    }
}
//BiThrTree pre;

void InThreading(BiThrTree T, BiThrTree *pre)   //递归的二叉树线索化
{
    if (T)
    {
        InThreading(T->lchild, pre);

        if (T->lchild == NULL)
        {
            T->LTag = Thread;
            T->lchild = *pre;
        }

        if ((*pre)->rchild == NULL)
        {
            (*pre)->RTag = Thread;
            (*pre)->rchild = T;
        }
        *pre = T;

        InThreading(T->rchild, pre);
    }
}

void UnRe_InTHreadin(BiThrTree T, BiThrTree *pre)  //非递归的二叉树线索化
{
    init_Stack(&S);
    BiThrTree tree = T;
    if (!tree)
    {
        printf("The tree is empty!\n");
    }
    else
    {
        while (tree || !isEmpty(S))
        {
            while (tree)
            {
                push_Stack(&S, tree);
                tree = tree->lchild;
            }
            pop_Stack(&S, tree);

            if (tree->lchild == NULL)
            {
                tree->LTag = Thread;
                tree->lchild = *pre;
            }
            if ((*pre)->rchild == NULL)
            {
                (*pre)->RTag = Thread;
                (*pre)->rchild = tree;
            }
            *pre = tree;
            tree = tree->rchild;
        }
    }
}

void In_Head_Threading(BiThrTree &Thrt, BiThrTree T)
{
    Thrt = (BiThrTree)malloc(sizeof(BiThrTNode));
    if (!Thrt)
    {
        exit(0);
    }
    Thrt->LTag = Link;
    Thrt->RTag = Thread;
    Thrt->rchild = Thrt;
    if (!T)
    {
        Thrt->lchild =Thrt;
        return;
    }
    BiThrTree pre;  //设置前驱
    pre = Thrt;
    Thrt->lchild = T;
   // InThreading(T, &pre);
    UnRe_InTHreadin(T, &pre);
    pre->rchild = Thrt;
    pre->RTag = Thread;
    Thrt->rchild = pre;
}

void InOrderTraveral(BiThrTree T)
{
    BiThrTree p = T->lchild;
    while (p != T)
    {
        while(p->LTag == Link)
        {
            p = p->lchild;
        }
        printf(" %c ", p->data);

        while(p->RTag == Thread && p->rchild != T)
        {
            p = p->rchild;
            printf("%c ", p->data);
        }
        p = p->rchild;
    }
}



int main()
{
    BiThrTree T;
    creat_Tree(T);  //非递归先序创建二叉树  Create a non-recursive preprder binary tree



    //在线索二叉树中新增一个头节点指向根节点
    //Add a header node to the root node in clue binary tree
    BiThrTree Tree;
    In_Head_Threading(Tree, T);

    //遍历线索二叉树  Traveral of the clue binary tree
    InOrderTraveral(Tree);

    return 0;
}


测试数据:ABD##E##CF##G##
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值