线索二叉树

本文详细介绍了中序线索二叉树的结构、类的声明,包括如何在二叉树中添加线索,以及中序线索链表的后继查找和遍历算法。主要涉及线索节点的设置、线索化过程和节点间的关系管理。
摘要由CSDN通过智能技术生成

目录:

1.结点结构

2.线索二叉树

(1)中序线索二叉树

类的声明:

中序线索二叉树的建立

如何定义pre

1.在线索二叉树中添加   

2.全局 变量

中序线索链表查找后继

中序线索链表的遍历算法

总代码


1.结点结构

struct ThreadNode
{
    DataType data;
    ThreadNode *lchild,*rchild;
    int itag,rtag;
};


2.线索二叉树

(1)中序线索二叉树

类的声明:

class ThreadBiTree
{
private:
    ThreadNode *root;
public:
    ThreadBiTree();
    ~ThreadBiTree();
    ThreadNode *next(ThreadNode *p);//查找p的后继
    void inOrder();
private:
    ThreadNode *creat(ThreadNode *bt);
    void inThread(ThreadNode *p);//线索化二叉树


};

大致逻辑【一步一步来的逻辑】:

1.p左孩子为空,设置前驱线索:【pre为空,不操作】
p的左孩子不为空,不操作
p->ltag=1;
p->lchild=pre(NULL);


2.pre右孩子为空,设置后继线索
pre右孩子不为空,不操作
pre->rtag=1;
pre->rchild=p;

3.用pre保存 p的内容,p指向下一个结点,也就是p分左孩子


实际上的逻辑就是【快速写的逻辑】

1.判断ltag和rtag和线索
如果一个结点有左孩子,那么ltag就为0,没有左孩子就为1
当ltag为1时,表示结点的左孩子那个地方的指针指向空,那么我们就建立
起一个联系,指向前驱(中序排列的后面一个)


如果一个结点有右孩子,那么rtag就为0,否则为1
当rtag为1时,表示结点的右孩子那个地方的指针指向空,那么我们就建立
起一个联系,指向后驱

中序线索二叉树的建立

void ThreadBiTree::inThread(ThreadNode *p)
{
    if(p==NULL)
    { 
        return;
    }
    
    inThread(p->lchild);
    
    if(p->lchild==NULL)
    {
        p->ltag=1;
        p->lchild=pre;
    }
    if(pre!=NULL&&pre->rchild==NULL)
    {
        pre->rtag=1;
        pre->rchild=p;
    }
    pre=p;
    
    inThread(p->rchild);
}


如何定义pre

1.在线索二叉树中添加   

class
{
private:
    ThreadNode *pre;

};

ThreadBiTree()
{
    pre=NULL;
    root=creat(root);
    inThread(root);
}


2.全局 变量

ThreadBiTree
{
    static ThreadNode *pre=NULL;
}

中序线索链表查找后继

我们来想一下前驱和后继是怎么查找的
1.首先如果没有左右孩子的话,那么他的左右孩子的指针
就是指向他的前驱和后继

2.如果他的右孩子为空,那么他就是指向后继
如果不为空,那么根据中序遍历,你就要找到右子树的最左边的那一个结点

如果左孩子为空那么就是指向前驱
如果不为空,那么根据中序遍历,你就要找到左子树的最右边的那一个结点

ThreadNode *ThreadBiTree::next(ThreadNode*p)
{
    if(p->rtag==1)
    {
        q=p->rchild;
    }
    else
    {
        q=p->rchild;
        while(q->ltag==0)
        {
            q=q->lchild;
        }
    }

    return q;

}

中序线索链表的遍历算法

void ThreadBiTree::inOrder()
{
    ThreadBode *p;
    if(root==NULL)
    {
        return;
    }
    
    p=root;
    while(p->ltag==0)//查找中序遍历中的第一个结点
    {
        p=p->lchild;
    }
    
    visit(p->data);//访问第一个结点
    
    while(p->rchild!=NULL)
    /*这个rchild是表示后继结点,
    如果有右孩子那么就指向右孩子,但是这个右孩子不一定是后继
    如果没有右孩子,那么rchild就直接指向后继
    */
    {
        p=next(p);
        visit(p->data);
    }
}

总代码

/*定义中序线索二叉树
运行范例:
abd#g###ce##f##      (教材PPT的例子)

基本的逻辑是:首先按照前序的顺序创建一颗二叉树,然后
将ltag和rtag赋初值,之后在将二叉树转化成线索二叉树(利用左孩子和右孩子中的
空指针)
将他转化从线索二叉树只需要一个函数,然后以中序遍历的方式去显示线索链表就需要两个函数
因为有两种情况
1.后序直接可以找到
2.后序不能直接找到

所以有一个找后序的函数和一个显示函数



*/
#include<iostream>
#include<stdio.h>
using  namespace  std;

struct  ThreadNode{
          char  data;
          ThreadNode    *lchild,  *rchild;
          int  ltag,  rtag;
};

class  ThreadBiTree{
private:
        ThreadNode  *root;//指向线索链表的头指针
public:

   ThreadNode *pre;

ThreadBiTree() {//构造函数,建立中序线索链表
        pre=NULL;
        root = NULL;
        root = creat(root);
        inThread(root);
    }



        ~ThreadBiTree();            //析构函数,释放各结点的存储空间
        ThreadNode  *next(ThreadNode  *p);    //查找p的后继
        void  inOrder();                                              //中序遍历线索链表
private:
        ThreadNode  *creat(ThreadNode  *bt);
        void  destroy(ThreadNode  *p);  //线索化,由构造函数调用

void inThread(ThreadNode *p); //线索化,由构造函数调用



};

//create函数创建二叉树
ThreadNode *ThreadBiTree::creat(ThreadNode *bt){
//在此处填写创建线索二叉树的代码
      char ch;
    cin>>ch;

    if(ch=='#')
    {
        bt=NULL;
    }

    else
    {
        bt=new ThreadNode ;
        bt->data=ch;
        bt->ltag=0;
        bt->rtag=0;
        bt->lchild=creat(bt->lchild);
        bt->rchild=creat(bt->rchild);
    }

    return bt;

}



//实现二叉树线索化,这个函数由构造函数调用
void ThreadBiTree::inThread(ThreadNode *p){
//在此处填写建立二叉树线索化的代码,注意,这个函数跟其他函数不同,它 的函数头可以修改,注意检查大括号是否匹配

    if(p==NULL)
    return;


    inThread(p->lchild);


       if(p->lchild==NULL)
       {
           p->ltag=1;
           p->lchild=pre;
       }

       if(pre!=NULL&&pre->rchild==NULL)
       {
           pre->rtag=1;
           pre->rchild=p;
       }
       pre=p;


       inThread(p->rchild);




}





//查找p的后继
ThreadNode* ThreadBiTree::next(ThreadNode *p){

   
    ThreadNode *q;
   
    if(p->rtag==1)
    {
        q=p->rchild;
    }
    else
    {
        q=p->rchild;
        while(q->ltag==0)
        {
            q=q->lchild;
        }
    }

    return q;

}



//中序遍历线索链表
void ThreadBiTree::inOrder(){

    //在此处填写中序遍历线索二叉树的代码
ThreadNode *p;
    if(root==NULL)
    {
        return;
    }

    p=root;
    while(p->ltag==0)//查找中序遍历中的第一个结点
    {
        p=p->lchild;
    }

   cout<<p->data;//访问第一个结点

    while(p->rchild!=NULL)
    /*这个rchild是表示后继结点,
    如果有右孩子那么就指向右孩子,但是这个右孩子不一定是后继
    如果没有右孩子,那么rchild就直接指向后继
    */
    {
        p=next(p);
      cout<<p->data;
    }

}




ThreadBiTree::~ThreadBiTree(){
   
 ThreadNode *q,*p;
    p=root;
    while(p->ltag==0)
    {
        p=p->lchild;
    }
    q=p;

    while(p->rchild!=NULL)
    {
        cout<<"delete "<<p->data<<endl;
        p=next(p);
        delete q;
        q=p;
    }

    cout<<"delete "<<p->data<<endl;
    delete p;


}



int  main(){
        ThreadBiTree  tree;
        cout  <<  "Inorder:";
        tree.inOrder();
        cout  <<  endl  <<  "Inorder  finished.  Calling  destructer..."<<endl;
        return  0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值