中序线索化二叉树

#include<stdio.h>
#include<stdlib.h>

#define ENDMARK 0//树叶子结束标志
#define datatype int

typedef enum{link,thread} tagtype;//定义枚举性tagtype 
typedef struct treenode//定义树结点结构体
{
    datatype num;
    struct treenode * lchild;
    struct treenode * rchild;
    tagtype ltag,rtag;//左右标记位
}treenode,*treeptr;

void creat_tree(treeptr * tree);//前序遍历,建立二叉树
void visit(treeptr tree);//访问结点
void InOrderTranverse(treeptr tree);//中序遍历二叉树
void InOrderThread(treeptr tree,treeptr * pre);//中序线索化
void InOrderThreading(treeptr * thead, treeptr tree);//添加头结点,实现中序线索化,形成循环链表
void InOrderThreading_Tranverse(treeptr thead);//利用非递归的方式遍历二叉树

void main()
{
    treeptr t,thead;
    creat_tree(&t);
    printf("tree not threaded is:\n");
    InOrderTranverse(t);
    printf("threaded tree is:\n");
    InOrderThreading(&thead, t);//添加头结点,实现中序线索化,形成循环链表
    InOrderThreading_Tranverse(thead);
    system("pause");
}

void creat_tree(treeptr * tree)//前序遍历,建立二叉树
{
    datatype temp;
    treeptr newnode;

    scanf("%d",&temp);
    if (temp==ENDMARK)
    {
        (*tree)=NULL;//结束
        return;
    }
    else
    {
        newnode = (treeptr)malloc(sizeof(treenode));//创建新结点及结点初值化
        newnode->num = temp;
        newnode->ltag = link;//初值皆为link
        newnode->rtag = link;
        *tree = newnode;
        creat_tree(&(*tree)->lchild);//遍历左子树
        creat_tree(&(*tree)->rchild);//遍历右子树        
    }
}

void InOrderTranverse(treeptr tree)//中序遍历二叉树
{
    if (tree==NULL)
    {
        return;
    }
    else
    {
        InOrderTranverse(tree->lchild);//遍历左子树
        visit(tree);
        InOrderTranverse(tree->rchild);//遍历左子树
    }
}

void visit(treeptr tree)//访问结点
{
    printf("%p,%p,%p,%d,%d,%d\n",tree,tree->lchild,tree->rchild,tree->num,tree->ltag,tree->rtag);
}
/*中序线索化二叉树其实就是
  将结点中的空指针改为指向
  前驱结点或后继结点的指针,
  从而将二叉树改为一个循环
  链表*/
void InOrderThread(treeptr tree,treeptr * pre)//中序线索化
{
    if (tree)
    {
        InOrderThread(tree->lchild, pre);//遍历左子树,找到该节点的最左边的叶子开始
        if(!tree->lchild)
        {
            tree->lchild=*pre;
            tree->ltag = thread;
        }   
        if(!(*pre)->rchild)
        {
            (*pre)->rchild = tree;
            (*pre)->rtag = thread;
        }
        (*pre)=tree;//当前结点为pre
        InOrderThread(tree->rchild, pre);//遍历由子树,找到该节点的最左边的叶子开始
    }
}

void InOrderThreading(treeptr * thead, treeptr tree)//添加头结点,实现中序线索化,形成循环链表
{
    treeptr newnode,pre;

    newnode = (treeptr)malloc(sizeof(treenode));
    *thead = newnode; 
    (*thead)->rchild = (*thead);//指定右孩子,非空
    (*thead)->rtag = thread;
    (*thead)->ltag = link;
    if (!tree)
    {
        (*thead)->lchild = (*thead);
    }
    else
    {
        (*thead)->lchild = tree;//添加头结点
    }
    pre = (*thead);
    InOrderThread(tree, &pre);//中序线索化二叉树
    pre->rchild = (*thead);
    pre->rtag = thread;
    (*thead)->rchild = pre;

}

void InOrderThreading_Tranverse(treeptr thead)//利用非递归的方式遍历线索化后的二叉树
{
    treeptr tree;
    tree = thead->lchild;
    while(tree!=thead)
    {
        while(tree->ltag==link)
        {
            tree = tree->lchild;//遍历到该节点下最左边的叶子
        }
        visit(tree);
        while(tree->rtag==thread&&tree->rchild!=thead)//到下一个含有右子树的根节点
        {
            tree = tree->rchild;
            visit(tree);
        }
        tree = tree ->rchild;//找到右子树叶子
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值