树-线索二叉树

/*
树-线索二叉树
LJK 2017-07-05
*/
#include<stdio.h>
#include<stdlib.h>
#include<math.h>

#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0

typedef char TElemType;
typedef int Status;

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

// 二叉线索存储节点结构
typedef struct biThrNode
{
    TElemType data;                            // 节点数据
    struct  biThrNode *lchild, *rchild;     // 左右孩子指针
    PointerTag LTag, RTag;                    // 左右标志
}BiThrNode;

int index = 0;
char String[] = "ABDH##I##EJ###CF##G##";

Status visit(TElemType e)
{
    printf("%c", e);
    return OK;
}

// 按前序输入二叉线索树中节点的值,构造二叉线索树
Status CreateBiThrTree(BiThrNode **T)
{
    TElemType ch;
    ch = String[index++];

    if (ch == '#')
        *T = NULL;
    else
    {
        *T = (BiThrNode*)malloc(sizeof(BiThrNode));
        if (!(*T)) exit(OVERFLOW);
        (*T)->data = ch;                // 生成根节点(前序)

        CreateBiThrTree(&(*T)->lchild); // 构造左子树
        if ((*T)->lchild)(*T)->LTag = Link;
        CreateBiThrTree(&(*T)->rchild); // 构造右子树
        if ((*T)->rchild) (*T)->RTag = Link;
    }
    return OK;
}

BiThrNode *pre;                         // 全局变量,始终指向刚刚访问过的节点

/* 中序遍历进行中序线索化 */
void InThreading(BiThrNode *p)
{
    if (p)
    {
        InThreading(p->lchild);     // 递归左子树线索化

        if (!p->lchild)                // 没有左孩子
        {
            p->LTag = Thread;        // 前驱线索
            p->lchild = pre;        // 左孩子指针指向前驱
        }

        if (!p->rchild)                // 前驱没有右孩子
        {
            pre->RTag = Thread;        // 后继线索
            pre->rchild = p;        // 前驱右孩子指针指向后继(当前节点p)
        }
        pre = p;                    // 保持pre指向p的前驱
        InThreading(p->rchild);        // 递归右子树线索化
    }
}

// 中序遍历二叉树T,并将其中序线索化,Thrt指向头节点
Status InOrderThreading(BiThrNode **Thrt, BiThrNode *T)
{
    *Thrt = (BiThrNode *)malloc(sizeof(BiThrNode)); // 建头节点
    if (!(Thrt)) exit(OVERFLOW);
    (*Thrt)->LTag = Link;
    (*Thrt)->RTag = Thread;
    (*Thrt)->rchild = *Thrt;                        // 右指针回指

    if (!(T)) (*Thrt)->lchild = *Thrt;                // 若二叉树空,则左指针回指
    else
    {
        (*Thrt)->lchild = T;        // 头节点左孩子指向根节点
        pre = (*Thrt);                // pre指向头节点

        InThreading(T);                // 中序遍历进行中序线索化

        pre->RTag = Thread;
        pre->rchild = *Thrt;        // 最后一个节点线索化,指向头节点
        (*Thrt)->rchild = pre;        // 头节点线索化,指向最后一个节点
    }
    return OK;
}

// 中序遍历二叉线索树T(头节点)的非递归算法
Status InOrderTraverse_Thr(biThrNode *T)
{
    BiThrNode *p;
    p = T->lchild;                        // p指向根节点
    while (p != T)
    {
        // 空树或者遍历结束时, p == T
        while (p->LTag == Link)
            p = p->lchild;
        if (!visit(p->data))                        // 访问其左子树为空的结点
            return ERROR;
        while (p->RTag == Thread && p->rchild != T) // 有后继线索则直接指向后继结点
        {
            p = p->rchild;
            visit(p->data);                            // 访问后继结点
        }
        p = p->rchild;                                // 进入右子树
    }
    return OK;
}

int main()
{
    BiThrNode *t, *h; 
    PointerTag P;

    printf("按前序输入二叉树(如:'ABDH##I##EJ###CF##G##')\n");
    CreateBiThrTree(&t);

    // 中序遍历,并中序线索化二叉树
    InOrderThreading(&h, t);

    // 中序遍历(输出),二叉线索树
    InOrderTraverse_Thr(h);
    printf("\n");

    getchar();
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/IamJiangXiaoKun/p/9453390.html