线索二叉树的建立与遍历

#include <stdio.h>
#include <stdlib.h>
typedef enum{LINK=0,THREAD} PointerTag;//为0表示右左右孩子,为1表示没有,则为线索
struct BiThrNode
{
    char data;//节点存储的数据
    BiThrNode* lchild,*rchild;//左右孩子
    PointerTag LTag;//坐标志,标志是否为孩子或是线索
    PointerTag RTag;//右标志,标志是否为孩子或是线索
};
//先用先序创建的方法创建一个二叉树
                                 //声明函数
void InThreading(BiThrNode* T);
//中序遍历线索化
BiThrNode *pre=NULL;//指向前一个节点

//这个是将头结点与我们的线索二叉树连起来 T是二叉树的根节点,Head是头结点,我们用一个指针的引用作为参数,这个效果同二级指针,可以改变指针的地址
void InOrderThreading(BiThrNode*T ,BiThrNode* & Head)
{
    //Head指针已经被改变
    Head=(BiThrNode*)malloc(sizeof(BiThrNode));
    if(Head)
    {
        Head->LTag=LINK;//让左节点标志为LINK
        Head->RTag=THREAD;
        Head->rchild=Head;
    }
    if(T)
    {
        Head->lchild=T;
        pre=Head;//让第一次的访问节点设置为头结点

        InThreading(T);
        //线索化完头pre已经指向了最右端的子节点
        pre->RTag=THREAD;
        //Head=PtMP;
        pre->rchild=Head;
        Head->rchild=pre;
    }else{
        Head->lchild=Head;
    }
}
//中序遍历线索二叉树,T表示头结点
void InOrderTraverse_THR(BiThrNode* T)
{
    BiThrNode* 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->rchild==T表示P指向了最右端的一个节点
        {
            //表明P的右子树不存在,所以我们得到指向指向后驱节点
            P=P->rchild;
            printf("%c",P->data);//打印后驱节点的值
        }
        //开始访问P的右子节点
        P=P->rchild;
    }
}
//创建二叉树
void Create_BiThrNode_ByPrev_2(BiThrNode** T)
{
    *T=(BiThrNode*)malloc(sizeof(BiThrNode));
    if(*T==NULL) exit(0);//开辟内存错误
    char ch;
    scanf("%c",&ch);
    if(ch=='#')
    {
        *T=NULL;
    }else{
        (*T)->data=ch;
        (*T)->LTag=LINK;//这一这个标志必须指定,要不然程序就会输不出所有结果(我为了找个问题,找了一个多小时。。。心酸。。)

        (*T)->RTag=LINK;
        Create_BiThrNode_ByPrev_2(&(*T)->lchild);
        Create_BiThrNode_ByPrev_2(&(*T)->rchild);
    }

}


void main()
{
    //先生成一个线索二叉树,带头结点
    BiThrNode* T=NULL;
    printf("请输入一个二叉树的结点,#表示空节点\n");
    Create_BiThrNode_ByPrev_2(&T);//先创建一颗二叉树
    //PrevOrderTraverse_NODE(T);
    BiThrNode* head=NULL;
    InOrderThreading(T,head);

    printf("\n");
    InOrderTraverse_THR(head);

    system("pause");

}





//这是一个线索化二叉树,但实际中我们还要真假一个头结点,让这个线索化二叉树连成链表
void InThreading(BiThrNode* T)
{
    BiThrNode *p=NULL;
    p=T;
    if(p)
    {
       InThreading(p->lchild);//递归左孩子
       //程序第一次执行到这时是在最左端的左子树节点
       if(!p->lchild)
       {
           //表明没有左孩子
           p->LTag=THREAD;
           p->lchild=pre;//指向上一次访问的节点
       }
       if (!pre->rchild)
       {
           //表明前驱没有右孩子
           pre->RTag=THREAD;//有标志置为THREAD指向后驱节点
           pre->rchild=p;//指向后继节点即上一个节点
       }
       pre=p;//保持pre指向前一个节点
       InThreading(p->rchild);//递归右子树
    }
}

上述代码注释的很详细,线索二叉树的概念就不做讲解了。(非常感谢数据结构第四版的书关于本算法的讲解)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值