大一从零开始的算法003---树和二叉树03

线索二叉树

        前情提要:二叉树的建立与遍历

问题提出:之前的二叉树只能向下走,一条路走到黑,回不去。

思考:如何利用没有孩子节点的节点的结构体内的空指针。

解决:对于上述问题,遇到结构体内存在空指针的情况下,可以用左孩子指针存放这个节点的来路(双亲指针),用右孩子结点存放这个节点的去路(对于不同的遍历方式来说只有中序遍历才可以,而且必须是完全二叉树)。其中来路和去路就是线索。

思路:引入ltag和rtag,tag为1时表明child指针指向的是线索,tag为0时表明child指针指向的是孩子。

#include
#include
 
typedef char ElemType;

//线索存储标志位
//Link{0}, 表示指向左右孩子的指针
//Thread{1}, 表示指向来源去路的指针
typedef enum {Link, Thread} PointierTag;
 
typedef struct BiThrTree
{
    char data;
    struct BiThrTree *lchild, *rchild;
    PointierTag ltag, rtag;
}BiThrNode, *BiThrTree;
 
//全局变量,始终指向上一个访问的节点
BiThrNode *Pre;

//创建树(前序)
void CreateBiThrTree(BiThrTree *T)
{
    char c;
    scanf("%c",&c);
    if(' ' == c)//没有就输入空格
    {
        *T = NULL;
    }
    else
    {
        *T = (BiThrNode*)malloc(sizeof(BiThrNode));
        (*T)->data = c;
        (*T)->ltag = Link;
        (*T)->rtag = Link;
        CreateBiThrTree(&(*T)->lchild);
        CreateBiThrTree(&(*T)->rchild);
    }
}
 
//访问树的节点
void visit1(char c, int level)
{
    printf("%c 位于 %d 层\n",c,level);
} 

//访问树的节点
void visit2(char c)
{
    printf("%c",c);
} 
 
//将树线索化(中序)
void Threaten(BiThrTree T)
{
    if(T)
    {
        Threaten(T->lchild);

        if(!T->lchild)
        {
            T->ltag = Thread;
            T->lchild = Pre;
        }

        if(!Pre->rchild)
        {
            Pre->rtag = Thread;
            Pre->rchild = T;
        }

        Pre = T;

        Threaten(T->rchild);
    }
}

void InOrderThreading(BiThrTree *p, BiThrTree T)
{
    *p = (BiThrNode*)malloc(sizeof(BiThrNode));
    (*p)->ltag = Link;
    (*p)->ltag = Thread;
    (*p)->rchild = *p;
    if(!T)
    {
        (*p)->lchild = *p;
    }
    else
    {
        (*p)->lchild = T;
        Pre = *p;

        Threaten(T);

        Pre->rchild = *p;
        Pre->rtag = Thread;
        (*p)->rchild = Pre;
    }

}

//遍历树(中序)(递归)
void MedTravelBiThrTree1(BiThrTree T, int level)
{
    if(T)
    {
        MedTravelBiThrTree1(T->lchild, level + 1);
        visit1(T->data,level);
        MedTravelBiThrTree1(T->rchild, level + 1);
    }
}

//遍历树(中序)(循环)
void MedTravelBiThrTree2(BiThrTree T)
{
    BiThrTree p;
    p = T->lchild;
    while(p != T)
    {
        while(p->ltag == Link)
        {
            p = p->lchild;
        }
        visit2(p->data);
        while(p->rtag == Thread && p->rchild != T)
        {
            p = p->rchild;
            visit2(p->data);
        }
    }
}
 
int main(void)    
{    
    int level = 1;
    BiThrTree P, T = NULL;
    CreateBiThrTree(&T);
    InOrderThreading(&P, T);
    MedTravelBiThrTree2(T);
 
    return 0;
}  

你可能感兴趣的:(c语言,算法,数据结构)