前序遍历线索化二叉树

女生的网名这么多〃 提交于 2019-11-26 12:44:56
#include <stdio.h>
#include <stdlib.h>
#define OK 1
#define ERROR 0
typedef enum PointerTag {Link,Thread};
typedef int Status;

typedef struct BiTNode
{
    char data;
    struct BiTNode *lchild,*rchild;
    enum PointerTag LTag,RTag;
}BiTNode,*BiTree;

int CreateBiTree(BiTree *T);
Status Visit(char e);
Status PreOrderThreadTraverse(BiTree T);
Status PreOrderThreadBackTraverse(BiTree T);
Status PreOrderThreading(BiTree Thrt,BiTree T);
void PreThreading(BiTree p,BiTree *pre);
Status PreOrderTraverse(BiTree T);

int main()
{
    BiTree *T,Thrt;
    T=(BiTree*)malloc(sizeof(BiTree));
    Thrt=(BiTree)malloc(sizeof(BiTNode));
    CreateBiTree(T);
    printf("\n前序遍历结果:");
    PreOrderTraverse(*T);
    PreOrderThreading(Thrt,*T);
	printf("\n线索化后前序正向遍历结果:");
	PreOrderThreadTraverse(Thrt);

    return 0;
}
int CreateBiTree(BiTree *T)
{
    fflush(stdin);
    printf("please input the node data:");
    char ch;
    scanf("%c",&ch);

    BiTree p;
    p=(BiTree)malloc(sizeof(BiTNode));
	p->data=ch;
	*T=p;
	char c;
	fflush(stdin);
	printf("Dose %c has left child(y--yes,n--no):",ch);
	scanf("%c",&c);
	if(c=='y')
		CreateBiTree(&(*T)->lchild);
	else
		(*T)->lchild=NULL;
	fflush(stdin);
    printf("Dose %c has right child(y--yes,n--no):",ch);
	scanf("%c",&c);
	if(c=='y')
		CreateBiTree(&(*T)->rchild);
	else
		(*T)->rchild=NULL;
    return 0;
}
Status Visit(char e)
{
    printf("%c ",e);
    return OK;
}
//按线索遍历线索二叉树:从第一个结点起顺后继进行遍历
Status PreOrderThreadTraverse(BiTree T)
{
    BiTree p;
    p=(BiTree)malloc(sizeof(BiTNode));
    p=T->lchild;  //从表头结点的左子树开始,即根结点;
    while(p!=T)  //如果表头结点的左子树指向自己,则为空树;
    {
        while(p->LTag==Link)
        {
            Visit(p->data);
            p=p->lchild;    //如果左标志为链接,则跳过不遍历,顺着链接往左传递,直到左标志为线索,才是第一个结点;
        }
        Visit(p->data);
        while(p->RTag==Thread && p->rchild!=T)
        {
            //只要右标志为线索,则顺着线索遍历,直到指向表头或者右标志为链接;
            p=p->rchild;
            Visit(p->data);
        }
        p=p->rchild;  //当右标志为链接时,跳过不遍历,顺着链接走;
    }
    return OK;
}

//前序线索化二叉树
Status PreOrderThreading(BiTree Thrt,BiTree T)
{
    Thrt->LTag=Link;    //表头结点左标志为链接,左指针指向根结点;
    Thrt->RTag=Thread;  //表头结点右标志为线索,右指针应指向后继,当前为自己;
    Thrt->rchild=Thrt;
    if(!T)
        Thrt->lchild=Thrt;  //如果二叉树为空,则左指针回转,指向自己;
    else
    {
        BiTree pre;
        pre=(BiTree)malloc(sizeof(BiTNode));  //用于保留前一结点

        Thrt->lchild=T;  //表头结点左指针指向根结点;
        pre=Thrt;        //表头结点成为前一结点;
        PreThreading(T,&pre);  //线索化当前结点;
        pre->rchild=Thrt;    //pre指向的前一结点为树中的最后一个结点,右指针应指向表头结点;
        pre->RTag=Thread;
        Thrt->rchild=pre;    //表头结点的右指针指向树的最后一个结点;
    }
    return OK;
}
//对单一结点线索化
void PreThreading(BiTree p,BiTree *pre)
{
    if(p)
    {

        //如果左子树为空,则左标志为线索,左指针指向前驱
        if(!p->lchild)
        {
            p->LTag=Thread;
            p->lchild=*pre;
        }
		else
			p->LTag=Link;  //如果左子树非空,则只需要改变左标志为链接,左指针不变;
        //如果前一节点的右子树为空,则其右标志为线索,右指针指向后继,即当前结点;
        if(!(*pre)->rchild)
        {
            (*pre)->RTag=Thread;
            (*pre)->rchild=p;
        }
		else
			(*pre)->RTag=Link;  //如果右子树非空,则只需要改变右标志为链接,右指针不变;

        *pre=p;  //将当前结点定义为前继结点,用于右子树的线索化;
        if(p->LTag==Link)
            PreThreading(p->lchild,pre);
        if(p->RTag==Link)
            PreThreading(p->rchild,pre);
    }
}
Status PreOrderTraverse(BiTree T)
{
    if(T)
    {
        if(Visit(T->data))
            if(PreOrderTraverse(T->lchild))
                if(PreOrderTraverse(T->rchild))
                    return OK;
        return ERROR;
    }
    else
        return OK;
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!