中序线索二叉树的创建、线索化和遍历(前序遍历和后序遍历)

线索二叉树的概念

线索二叉树的原理:线索二叉树是将普通二叉树左右孩子中的空链域利用起来,将左孩子空链域指向当前节点的线性遍历前驱,将右孩子空链域指向当前节点的线性遍历后继,指向该线性序列中的前驱或后继被称为“线索”。由于在线索链表中添加了遍历中得到的“前驱”和“后继”的信息,从而简化了遍历的算法。

线索二叉树的结构

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

#define END '#'
typedef char ElemType;
typedef enum{Link = 0,Thread = 1}PointTag;

typedef struct ThrBiTreeNode
{
    PointTag ltag,rtag;
    struct ThrBiTreeNode  *lchild;
    struct ThrBiTreeNode  *rchild;
    ElemType data;
}ThrBiTreeNode,*ThrBiTree;

中序线索二叉树的创建和遍历

线索二叉树结点的申请和释放

ThrBiTreeNode * BuyNode()
{
    ThrBiTreeNode * node = (ThrBiTreeNode *)malloc(sizeof(ThrBiTreeNode));
    assert(NULL != node);
    memset(node,0,sizeof(node));
    return node;
}

void FreeNode(ThrBiTreeNode *ptr)
{
    assert(ptr != NULL);
    free(ptr);
}

线索二叉树的创建

ThrBiTreeNode * CreateThrBiTree(ElemType *&str)
{
    ThrBiTreeNode *node = NULL;
    if (str != NULL && *str != END)
    {
        node = BuyNode();
        node->ltag = Link;
        node->rtag = Link;
        node->data = *str;
        node->lchild = CreateThrBiTree(++str);
        node->rchild = CreateThrBiTree(++str);
    }
    return node;
}

中序线索化二叉树

方法1

//中序线索化二叉树
ThrBiTreeNode *pre = NULL;

void MakeThreadBiTree(ThrBiTreeNode *ptr)
{
    if(ptr != NULL)
    {
        MakeThreadBiTree(ptr->lchild);
        if(ptr->lchild == NULL)
        {
            ptr->lchild = pre;
            ptr->ltag = Thread;
        }
        if (pre != NULL && pre->rchild == NULL)
        {
            pre->rchild = ptr;
            pre->rtag = Thread;
        }
        pre = ptr;
        if (pre->rchild == NULL && pre->rtag == Link)
        {
            pre->rtag = Thread;
        }
        MakeThreadBiTree(ptr->rchild);
    }
}

方法2(带头结点的线索二叉树)

// 中序遍历二叉树T,并将其中序线索化,Thrt指向头结点
void InOrderThreading(ThrBiTree *Thrt,ThrBiTree T)
{ 
    *Thrt = (ThrBiTree)malloc(sizeof(ThrBiTreeNode));
    if(!*Thrt)
        exit(OVERFLOW);
    (*Thrt)->ltag=Link; /* 建头结点 */
    (*Thrt)->rtag=Thread;
    (*Thrt)->rchild=(*Thrt); /* 右指针回指 */
    if(!T) /* 若二叉树空,则左指针回指 */
        (*Thrt)->lchild=*Thrt;
    else
    {
        (*Thrt)->lchild=T;
        pre=(*Thrt);
        MakeThreadBiTree(T); /* 中序遍历进行中序线索化 */
        pre->rchild=*Thrt;
        pre->rtag=Thread; /* 最后一个结点线索化 */
        (*Thrt)->rchild=pre;
    }
}

方法3

void Make(ThrBiTreeNode *ptr,ThrBiTreeNode *&pre)
{
    if(ptr != NULL)
    {
        Make(ptr->lchild,pre);
        if(ptr->lchild == NULL)
        {
            ptr->lchild = pre;
            ptr->ltag = Thread;
        }
        if (pre != NULL && pre->rchild == NULL)
        {
            pre->rchild = ptr;
            pre->rtag = Thread;
        }
        pre = ptr;
        if (pre->rchild == NULL && pre->rtag == Link)
        {
            pre->rtag = Thread;
        }
        Make(ptr->rchild,pre);
    }
}

ThrBiTreeNode * MakeThreadBiTree2(ThrBiTreeNode *ptr)
{
    if(ptr == NULL)
    {
        return NULL;
    }
    ThrBiTreeNode *pre = NULL;
    Make(ptr,pre);
    return ptr;
}

中序线索二叉树的遍历

前序遍历
方法1

void ThrInOrder(ThrBiTreeNode *ptr)
{
    assert(ptr != NULL);
    ThrBiTreeNode *p;
    p = ptr;
    while (p != NULL)
    {
        while (p->ltag == Link)
        {
            p = p->lchild;
        }
        printf("%c ",p->data);
        while (p->rtag == Thread && p->rchild != NULL)
        {
            p = p->rchild;
            printf("%c ",p->data);
        }
        p = p->rchild;
    }
}

方法2(带头结点的线索二叉树)

/* 中序遍历二叉线索树T(头结点)的非递归算法 */
void InOrderTraverse_Thr(ThrBiTree T)
{ 
    ThrBiTree p;
    p=T->lchild; /* p指向根结点 */
    while(p!=T)
    { /* 空树或遍历结束时,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;
    }
}

方法3

ThrBiTreeNode * First(ThrBiTreeNode *ptr)
{
    while (ptr != NULL && ptr->ltag == Link)
    {
        ptr = ptr->lchild;
    }
    return ptr;
}

ThrBiTreeNode * Next(ThrBiTreeNode *ptr)
{
    if (ptr != NULL && ptr->rtag == Thread)
    {
        return ptr->rchild;
    }
    else
    {
        return First(ptr->rchild);
    }
}

void ThrInOrder2(ThrBiTreeNode *ptr)
{
    for (ThrBiTreeNode * temp = First(ptr);temp != NULL;temp = Next(temp))
    {
        printf("%c ",temp->data);
    }
    printf("\n");
}

后序遍历
方法1

void ThrInOrderReverse(ThrBiTreeNode *ptr)
{
    assert(ptr != NULL);
    ThrBiTreeNode *p;
    p = ptr;
    while (p != NULL)
    {
        while (p->rtag == Link)
        {
            p = p->rchild;
        }
        printf("%c ",p->data);
        while (p->ltag == Thread && p->lchild != NULL)
        {
            p = p->lchild;
            printf("%c ",p->data);
        }
        p = p->lchild;
    }
}

方法2(带头结点的线索二叉树)

void ThrInOrderReverse2(ThrBiTree T)
{
    ThrBiTree p;
    p=T->lchild; /* p指向根结点 */
    while(p!=T)
    { /* 空树或遍历结束时,p==T */
        while(p->rtag==Link)
            p=p->rchild;
        printf("%c ",p->data);

        while(p->ltag==Thread&&p->lchild!=T)
        {
            p=p->lchild;
            printf("%c ",p->data); /* 访问后继结点 */
        }
        p=p->lchild;
    }
}

方法3

ThrBiTreeNode * Last(ThrBiTreeNode *ptr)
{
    while(ptr != NULL && ptr->rtag != Thread)
    {
        ptr = ptr->rchild;
    }
    return ptr;
}

ThrBiTreeNode * Prev(ThrBiTreeNode *ptr)
{
    if (ptr != NULL && ptr->ltag == Thread)
    {
        return ptr->lchild;
    }
    else
    {
        return Last(ptr->lchild);
    }
}

void ResThrInOrder(ThrBiTreeNode *ptr)
{
    ThrBiTreeNode * temp;
    for (temp = Last(ptr);temp != NULL;temp = Prev(temp))
    {
        printf("%c ",temp->data);
    }
    printf("\n");
}
  • 3
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值