线索化二叉树

//不含头结点的二叉树线索化
#include<iostream>
using namespace std;

//二叉树结构体
typedef char elemType;
struct BTNode
{
    elemType data;//数据域
    BTNode *lChild, *rChild;//左右孩子
    int lFlag, rFlag;//表明左右孩子的数据域实际内容
    //当lFlag为0表示lChild为左孩子,当lFlag为1表示lChild为前驱
    //当rFlag为0表示rCHild为右孩子,当rFlag为1表示lCHild为后继
};

typedef BTNode *BTree;

//先序创建二叉树
void preCreateBTree(BTree &bt);
//中序线索化的二叉树
void inOrderCueBTree(const BTree &bt, BTree &pre);
//中序遍历中序线索化后的二叉树
void inOrderBTree(const BTree &bt);
//访问结点
void visit(BTNode *node);

int main()
{
    BTree bt;
    preCreateBTree(bt);
    //ABD#G###CE#H##F##
    BTNode *pre = NULL;
    inOrderCueBTree(bt, pre);
    pre -> rFlag = 1;//在线索化结束之后,pre指向的那个结点是哦没有右孩子的,所以为1
    inOrderBTree(bt);
    cout << endl;
    return 0;
}

//先序创建二叉树
void preCreateBTree(BTree &bt)
{
    elemType elem;
    cin >> elem;
    if (elem == '#')
    {
        bt = NULL;
    }
    else
    {
        bt = new BTNode;
        bt -> data = elem;
        preCreateBTree(bt -> lChild);
        preCreateBTree(bt -> rChild);
    }
}
//中序线索化的二叉树
//按照上面对lFlag和rFlag的定义可以看出,线索化是合理使用lChild和rChild,
//使得二叉树数据域充分的使用,最后达到不使用栈的情况先就可以遍历二叉树
void inOrderCueBTree(const BTree &bt, BTree &pre)
{
    if (bt)
    {
        inOrderCueBTree(bt -> lChild, pre);
        //确定bt前驱
        if (bt -> lChild == NULL)
        {
            bt -> lFlag = 1;
            bt -> lChild = pre;
        }
        else
            bt -> lFlag = 0;

        //确定pre后继
        if (pre)
        {
            if (pre -> rChild == NULL)
            {
                pre -> rFlag = 1;
                pre -> rChild = bt;
            }
            else
                pre -> rFlag = 0;
        }

        pre = bt;

        inOrderCueBTree(bt -> rChild, pre);
    }
}
//不带头结点中序遍历中序线索化后的二叉树
void inOrderBTree(const BTree &bt)
{
    BTNode *node = bt;
    while (node)
    {
        while (node -> lFlag == 0)
        {
            node = node -> lChild;
        }
        visit(node);
        while (node -> rChild && node -> rFlag == 1)
        {
            node = node -> rChild;
            visit(node);
        }

        node = node -> rChild;
    }
}
//访问结点
void visit(BTNode *node)
{
    cout << node -> data;
}
//含头结点的二叉树线索化
//头结点的lChild执行根节点,rChild指向线索化后的最后一个结点,
//这个结点的rChild指向头结点
#include<iostream>
using namespace std;

//二叉树结构体
typedef char elemType;
struct BTNode
{
    elemType data;//数据域
    BTNode *lChild, *rChild;//左右孩子
    int lFlag, rFlag;//表明左右孩子的数据域实际内容
    //当lFlag为0表示lChild为左孩子,当lFlag为1表示lChild为前驱
    //当rFlag为0表示rCHild为右孩子,当rFlag为1表示lCHild为后继
};

typedef BTNode *BTree;

//先序创建二叉树
void preCreateBTree(BTree &bt);
//为线索化二叉树创建头结点
void createHeadForInOrderCueBtree(BTree &head,const BTree &bt);
//中序线索化的二叉树
void inOrderCueBTree(const BTree &bt, BTree &pre);
//中序遍历中序线索化后的二叉树
void inOrderBTree(const BTree &bt);
//访问结点
void visit(BTNode *node);

int main()
{
    BTree bt, head;
    preCreateBTree(bt);
    //ABD#G###CE#H##F##

    createHeadForInOrderCueBtree(head, bt);
    inOrderBTree(head);
    cout << endl;
    return 0;
}

//先序创建二叉树
void preCreateBTree(BTree &bt)
{
    elemType elem;
    cin >> elem;
    if (elem == '#')
    {
        bt = NULL;
    }
    else
    {
        bt = new BTNode;
        bt -> data = elem;
        preCreateBTree(bt -> lChild);
        preCreateBTree(bt -> rChild);
    }
}
//为线索化二叉树创建头结点
void createHeadForInOrderCueBtree(BTree &head,const BTree &bt)
{
    head = new BTNode;
    head -> lFlag = head -> rFlag = 0;
    head -> rChild = head;

    if (bt -> lChild == NULL)
    {
        head -> lChild = head;//根节点没有左孩子,那根节点就是第一个点,直接指向头结点
    }
    else
    {
        head -> lChild = bt;//不是,指向根节点
        BTNode * pre = head;
        inOrderCueBTree(bt, pre);
        //按照规定设置头结点和最后结点的rChild
        pre -> rFlag = 1;
        pre -> rChild = head;
        head -> rFlag = 1;
        head -> rChild = pre;
    }
}
//中序线索化的二叉树
//按照上面对lFlag和rFlag的定义可以看出,线索化是合理使用lChild和rChild,
//使得二叉树数据域充分的使用,最后达到不使用栈的情况先就可以遍历二叉树
void inOrderCueBTree(const BTree &bt, BTree &pre)
{
    if (bt)
    {
        inOrderCueBTree(bt -> lChild, pre);
        //确定bt前驱
        if (bt -> lChild == NULL)
        {
            bt -> lFlag = 1;
            bt -> lChild = pre;
        }
        else
            bt -> lFlag = 0;

        //确定pre后继
        if (pre)
        {
            if (pre -> rChild == NULL)
            {
                pre -> rFlag = 1;
                pre -> rChild = bt;
            }
            else
                pre -> rFlag = 0;
        }

        pre = bt;

        inOrderCueBTree(bt -> rChild, pre);
    }
}
//不带头结点中序遍历中序线索化后的二叉树
void inOrderBTree(const BTree &head)
{
    BTNode *node = head -> lChild;
    while (node != head)
    {
        while (node -> lFlag == 0)
        {
            node = node -> lChild;
        }
        visit(node);
        while (node -> rChild != head && node -> rFlag == 1)
        {
            node = node -> rChild;
            visit(node);
        }

        node = node -> rChild;
    }
}
//访问结点
void visit(BTNode *node)
{
    cout << node -> data;
}

猜你喜欢

转载自blog.csdn.net/cheng_cuo_tuo/article/details/80257602