数据结构笔记(十八)线索化二叉树

//线索化规则为

//叶子结点指向NULL的两个指针利用起来

//结点的左指针,指向其当前遍历顺序的前驱结点

//结点的右指针,指向其当前遍历顺序的后继结点

//此外还需要左右加一个标志位,来表示左右指针是指孩子还是遍历线索



#include<stdio.h>

#include<stdlib.h>





typedef char E;//树结点的储存元素类型

typedef struct TreeNode{

    E element;//存储数据

    struct TreeNode* left;//左指针

    struct TreeNode* right;//右指针

    int leftflag;//左标志位

    int rightflag;//右标志位

    struct TreeNode* parent;//后序遍历线索化使用,存父结点

    //当标志位为1代表指向孩子,不为1代表指向线索

}*Node;





//创建树结点

Node creatTreeNode(E element)

{

    Node node =malloc(sizeof(struct TreeNode));

    node->left=node->right=NULL;

    node->leftflag=node->rightflag=0;

    node->element=element;

    return node;

}

//前序遍历线索化函数

//函数外面存一下上一个结点,等到遍历到空的时候可以用指针返回

Node pre = NULL;

void preOrderThreaded(Node root)

{

    if(root==NULL)

    {

        return;

    }

    if(root->left==NULL)//当遍历到左指针为空时意味着到了叶子结点

    {

        root->left=pre;//指向上一个结点

        root->leftflag=1;

    }

    if(pre&&pre->right==NULL)//上一个结点右结点如果为空指向下一个结点(保证上一个结点不为空防止刚开始报错)

    {

        pre->right=root;//指向下一个结点

        pre->rightflag=1;    

    }

    pre = root;

    if(root->leftflag==0)//没有建立线索继续走

        preOrderThreaded(root->left);

    if(root->rightflag==0)//没有建立线索继续走

        preOrderThreaded(root->right);

}

//快速遍历一个前序遍历线索化的二叉树

void preOrder(Node root)

{

    while(root)

    {

        printf("%c",root->element);

        if(root->leftflag==0)

        {

            root=root->left;

        }

        else

        {

            root=root->right;

        }

    }

}

//中序遍历线索化函数

//函数外存一个变量指向上一个结点

Node in = NULL;

void inOrderThreaded(Node root)

{

    if(root==NULL)

    {

        return;

    }

    //如果左标志为0则说明左边为子结点,往下遍历直到为空代表到了叶子结点

    if(root->leftflag==0)

    {

        inOrderThreaded(root->left);//到空时返回上一个结点(叶子结点)

    }

    if(root->left==NULL)

    {

        root->left=in;//上一个结点值给in

        root->leftflag=1;//左边标记为1即被线索化

    }

    if(in&&in->right==NULL)

    {

        in->right=root;//如果in不为空且in的右边为空,则in为上一个结点,将in的右结点指向下一个结点

        in->rightflag=1;//右标记线索化

    }

    in = root;//in变为下一个结点

    if(root->rightflag==0)

    inOrderThreaded(root->right);//向右遍历

}

//快速遍历一个中序遍历线索化的二叉树

void inOrder(Node root)

{

    while(root)

    {

        //向左遍历直到左标记不等于0即线索化

        while(root&&root->leftflag==0)

        {

            root=root->left;

        }

        printf("%c",root->element);//打印这个结点

        //如果右为线索化向右继续遍历

        while(root&&root->rightflag==1)

        {

            root=root->right;

            printf("%c",root->element);

        }

        //如果右有子节点不是线索化则向右走

        root=root->right;

    }

}

//后序遍历线索化函数

//函数外存一个变量指向上一个结点

Node post = NULL;

void postOrderThreaded(Node root)

{

    if(root==NULL)

    {

        return;

    }

    

    if(root->leftflag==0)

    {

        postOrderThreaded(root->left);

        if(root->left)

        {

            root->left->parent = root;

        }

    }

    if(root->rightflag==0)

    {

        postOrderThreaded(root->right);

        if(root->right)

        {

            root->right->parent = root;

        }

    }

    if(root->left==NULL)

        {

            root->left=post;

            root->leftflag=1;

        }

        if(post&&post->right==NULL)

        {

            post->right=root;

            post->rightflag=1;

        }

        post = root;

}

//快速遍历一个后序遍历线索化的二叉树

void postOrder(Node root)

{

    Node last = NULL;//暂存指针,记录上一次遍历结点

    Node node = root;//记录根结点

    while(node)

    {

        //左遍历一直找到左结点为空且未被线索化的叶子结点

        while(node->left!=last&&node->rightflag==0)

        {

            node = node->left;

        }

        //如果右边是线索直接打印走

        while(node&&node->rightflag==1)

        {

            printf("%c",node->element);

            last = node;

            node = node->right;

        }

        //如果是根结点直接返回

        if(node==root)

        {

            printf("%c",node->element);

            return;

        }

        //如果当前结点的右孩子是上一个结点

        while(node&&node->right==last)

        {

            printf("%c",node->element);//直接打印

            last = node;

            node = node->parent;//继续找父结点

        }

        if(node&&node->rightflag==0)

        {

            //右边不是线索往右走

            node=node->right;

        }

    }

    

}

int main()

{

    //创建一棵简单的二叉树

    Node a = creatTreeNode('A');

    Node b = creatTreeNode('B');

    Node c = creatTreeNode('C');

    Node d = creatTreeNode('D');

    Node e = creatTreeNode('E');

    

    a->left=b;

    a->right=c;

    b->left=d;

    b->right=e;

    

    postOrderThreaded(a);

    postOrder(a);

    return 0;

}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值