中序线索化二叉树

本文介绍了一种实现中序线索化二叉树的方法,包括创建二叉树、线索化过程及遍历线索化后的二叉树。通过具体代码实现了二叉树的创建、中序线索化以及遍历输出,有助于深入理解线索二叉树的概念。

这里写图片描述
这里写图片描述

/*
线索化二叉树。 
(1)中序线索化二叉树; 
(2)遍历线索化二叉树。 
*/  
#include <iostream>  
#include <malloc.h>  
#define MaxSize 100  
typedef char ElemType;  
using namespace std;  
typedef struct node  
{  
    ElemType data;  
    int ltag,rtag;  
    struct node *lchild;  
    struct node *rchild;  
} TBTNode;  

/* 
对以*p为根节点的二叉树中序线索化。 
算法思路: 
 在指针不为NULL时,先对*p节点的左子树线索化,若*p没有左孩子节点,则将其lchild指针线索化为指向其前驱节点*pre,将其ltag置为1, 
 若*pre节点的rchild指针为NULL,将其rchild指针线索化为指向其后继节点*p,将其rtag置为1;最后对*p节点的右子树线索化。 
*/  
TBTNode *pre;  
void Thread(TBTNode *&p)  
//先对*p进行前驱节点线索化,再对*pre进行后继节点线索化,而并不是*p的后继节点,方便。  
{  
    if(p!=NULL)  
    {  
        Thread(p->lchild);     //左子树线索化  
        if(p->lchild==NULL)    //*p左孩子不存在:进行前驱节点线索化  
        {  
            p->lchild=pre;  
            p->ltag=1;  
        }  
        else  
            p->ltag=0;  
        if(pre->rchild==NULL)   //*pre右孩子不存在,进行后继节点线索化  
        {  
            pre->rchild=p;  
            pre->rtag=1;  
        }  
        else  
            pre->rtag=0;  
        pre=p;  
        Thread(p->rchild);     //右子树线索化  
    }  
}  

/*  
将以二叉链存储的二叉树b进行中序线索化,并返回线索化后头节点指针root。  
*/  
TBTNode *CreaThread(TBTNode *b)   //中序线索化二叉树  
{  
    TBTNode *root;  
    root=(TBTNode *)malloc(sizeof(TBTNode));  
    root->ltag=0;  
    root->rtag=1;             //建立头节点  
    root->rchild=b;           //建立头节点与二叉树的联系  
    if(b==NULL)  
        root->lchild=root;    //空二叉树  
    else  
    {  
        root->lchild=b;  
        pre=root;  
        Thread(b);            //中序遍历线索化二叉树  
        //最后处理,加入指向头节点的线索  
        pre->rchild=root;  
        pre->rtag=1;  
        root->rchild=pre;      //头节点右线索化  
    }  
    return root;  
}  

void CreateTBTNode(TBTNode * &b,char *str)  
{  
    TBTNode *St[MaxSize],*p=NULL;  
    int top=-1,k,j=0;  
    char ch;  
    b=NULL;             //建立的二叉树初始时为空  
    ch=str[j];  
    while (ch!='\0')    //str未扫描完时循环  
    {  
        switch(ch)  
        {  
        case '(':  
            top++;  
            St[top]=p;  
            k=1;  
            break;      //为左结点  
        case ')':  
            top--;  
            break;  
        case ',':  
            k=2;  
            break;                          //为右结点  
        default:  
            p=(TBTNode *)malloc(sizeof(TBTNode));  
            p->data=ch;  
            p->lchild=p->rchild=NULL;  
            if (b==NULL)                    //*p为二叉树的根结点  
                b=p;  
            else                            //已建立二叉树根结点  
            {  
                switch(k)  
                {  
                case 1:  
                    St[top]->lchild=p;  
                    break;  
                case 2:  
                    St[top]->rchild=p;  
                    break;  
                }  
            }  
        }  
        j++;  
        ch=str[j];  
    }  
}  

void DispTBTNode(TBTNode *b)  //输出二叉树  
{  
    if(b!=NULL)  
    {  
        cout<<b->data;  
        if(b->lchild!=NULL||b->rchild!=NULL)  
        {  
            cout<<"(";       //有孩子节点才输出  
            DispTBTNode(b->lchild);   //递归处理左子树  
            if(b->rchild!=NULL)  
                cout<<",";          //有右孩子节点时才输出  
            DispTBTNode(b->rchild);   //递归处理右子树  
            cout<<")";             //有孩子节点时才输出  
        }  
    }  
}  

/*  
遍历线索化二叉树:  
  算法思想:  
     遍历某种次序的线索二叉树,从该次序的开始节点出发;反复找到该节点在该次序下的后继节点,直到终端节点,  
     其rchild指针被线索化为指向头节点。  
  (在中序二叉树中,开始节点就是根节点的最左下节点)  
*/  
void ThInOrder(TBTNode *tb)  
{  
    TBTNode *p=tb->lchild;      //指向根结点  
    while (p!=tb)  
    {  
        while (p->ltag==0)     //找开始节点  
            p=p->lchild;  
        cout<<p->data<<" ";   //访问开始节点  
        while (p->rtag==1 && p->rchild!=tb)  
        {  
            p=p->rchild;  
            cout<<p->data<<" ";  
        }  
        p=p->rchild;  
    }  
}  

int main()  
{  
    TBTNode *b,*tb;  
    CreateTBTNode(b,"A(B(D(,G)),C(E,F))");  
    cout<<" 二叉树:";  
    DispTBTNode(b);  
    cout<<endl;  
    tb=CreaThread(b);  
    cout<<" 线索中序序列:";  
    ThInOrder(tb);  
    cout<<endl;  
    return 0;  
}  
线索化二叉树
1.创建二叉树
2.先序递归遍历输出二叉树
3.线索化二叉树
4.输出线索化二叉树
/*
线索化二叉树
    1.创建二叉树
    2.先序递归遍历输出二叉树
    3.线索化二叉树
    4.输出线索化二叉树
*/

#include<iostream>
#include<stack>
#include<string>
#include<fstream>
using namespace std;

class Node
{
public:
    char data;
    bool ltag, rtag;
    class Node *lchild, *rchild;
};

class Thread_Binary_Tree
{
public:

    Thread_Binary_Tree(){}
    ~Thread_Binary_Tree(){}

    //创建二叉树
    void create_binary_tree(string filename)
    {
        ifstream readfile;
        string str;
        readfile.open(filename,ios::in);
        getline(readfile,str);
        cout << str << endl;
        Create_Tree(str);//创建二叉树
        readfile.close();
    }


    //先序递归输出二叉树
    void displayFront_tree()
    {
        cout << "先序递归输出" << endl;
        output_fro(t);//递归先序输出
        cout << endl;
    }

    //创建线索化二叉树
    void create_thread_Btree()
    {
        thread_root = CreateThread(t);
    }

    //输出线索化二叉树
    void display_thread_Btree()
    {
        cout << "中序线索化输出" << endl;
        output_thread(thread_root);
        cout << endl;
        cout << "中序线索化新根节点左右标记" << endl;
        cout << thread_root->ltag << "," << thread_root->rtag << endl;//输出中序线索化新根节点左右标记
    }
private:
    Node *t;
    Node *pre;
    Node *thread_root;
    //创建二叉树
    void Create_Tree(string str)
    {
        stack<Node *> m_stack;
        int k;
        Node *p;
        while (!str.empty())
        {
            if (str[0] == '(')
            {
                m_stack.push(p);
                k = 1;
            }
            else if (str[0] == ')')//必须使用if-else if
            {
                m_stack.pop();
            }
            else if (str[0] == ',')
            {
                k = 2;
            }
            else
            {
                p = (Node *)malloc(sizeof(Node));
                p->lchild = p->rchild = NULL;
                p->data = str[0];//将串首字符赋给data
                if (t == NULL)//处理根节点
                {
                    t = p;
                }
                else
                {
                    if (k == 1)
                    {
                        m_stack.top()->lchild = p;//左子树
                    }
                    if (k == 2)
                    {
                        m_stack.top()->rchild = p;//右子树
                    }
                }
            }
            str.assign(str.substr(1, str.length() - 1));//构建新串,将串首字符除去
        }
    }

    //先序递归输出二叉树
    void output_fro(Node *t)
    {
        if (t == NULL)
        {
            return;
        }
        else
        {
            cout << t->data;
            if (t->lchild != NULL || t->rchild != NULL)
            {
                cout << "(";
                output_fro(t->lchild);//先序递归左子树
                if (t->rchild != NULL)
                {
                    cout << ",";
                }
                output_fro(t->rchild);//先序递归右子树
                cout << ")";
            }
        }
    }

    //中序线索化二叉树
    void Thread(Node *&p)
    {
        if (p != NULL)
        {
            Thread(p->lchild);//向左直走
            if (p->lchild == NULL)//遍历到中序遍历输出的首节点且无左子节点
            {
                p->lchild = pre;//指向前驱节点
                p->ltag = true;
            }
            else//存在左子节点
            {
                p->ltag = false;
            }
            if (pre->rchild == NULL)//若右节点无子节点,则右指针指向后继节点
            {
                pre->rchild = p;
                pre->rtag = true;
            }
            else//存在右子节点
            {
                pre->rtag = false;
            }
            pre = p;//更新
            Thread(p->rchild);//处理右子树
        }
    }

    //创建线索化二叉树
    Node *CreateThread(Node *t)
    {
        Node *root;
        root = (Node *)malloc(sizeof(Node));//生成附加根节点
        root->ltag = false; root->rtag = true;
        root->rchild = t;
        if (t == NULL)//空树线索化
        {
            root->lchild = root;
        }
        else
        {
            root->lchild = t;
            pre = root;//pre初始化
            Thread(t);//线索化二叉树
            pre->rchild = root;//中序末节点
            pre->rtag = true;
            root->rchild = pre;//新生成根节点
            root->rtag = 1;//新生成根节点rtag=1;
        }
        return root;
    }

    //遍历输出线索化二叉树
    void output_thread(Node *t)
    {
        Node *p = t->lchild;
        while (p != t)
        {
            while (!p->ltag)
            {
                p = p->lchild;
            }
            cout << p->data << ends;

            while (p->rtag&&p->rchild != t)
            {
                p = p->rchild;
                cout << p->data << ends;
            }
            p = p->rchild;
        }

    }
};

int main()
{
    Thread_Binary_Tree m_tree;
    m_tree.create_binary_tree("data");//创建普通二叉树
    m_tree.displayFront_tree();//先序递归遍历输出
    m_tree.create_thread_Btree();//创建中序线索化二叉树
    m_tree.display_thread_Btree();//输出中序线索化二叉树
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值