线索二叉树

       二叉树作为存储结构只能保存其左右孩子结点信息,不能获取结点的前驱和后继信息。同时二叉树结构存在很多个空指针域。一个n个结点的二叉树会形成n+1个空指针域。可以利用这些空指针完成结点前驱和后继信息的补充。具体方法如下:将结点中lchild为空的指针指向其前驱结点;将结点中rchild为空的指针指向其后继结点。指向前驱和后继的指针称为线索。加上线索的二叉树结构称为线索二叉树。

    

     程序说明:使用Qt完成,输入输出使用的Qt类

                         前序顺序构建二叉树。用中序遍历添加线索

                         可以完成二叉树的正向遍历和反向遍历

                         添加头节点使得整个二叉树形成一个环状


头文件:

typedef enum{Link,Thread} TagType;

struct BiThrNode
{
 char data;
 BiThrNode *lchild,*rchild;
 TagType lTag,rTag;
};

class BiThrTree
{
public:
    explicit BiThrTree();
    ~BiThrTree();
    BiThrNode *createBiTree();
    void deleteBiThrTree(BiThrNode *node);
    BiThrNode *getRoot();
    void Thr_InOrder_Forward(BiThrNode *header);//线索二叉树中序正向遍历
    void Thr_InOrder_Reverse(BiThrNode *header);//线索二叉树中序反向遍历

private:
    void inThreading(BiThrNode *currentNode);//中序线索化二叉树
    BiThrNode *inThreading_addHeader(BiThrNode *root);//为线索二叉树添加头结点以形成一个闭合的环
    BiThrNode *m_root=nullptr;
    BiThrNode *pre=nullptr  ;//记录刚刚访问过的结点

};


cpp:

#include "bithrtree.h"
#include <QDebug>
#include <QTextStream>

BiThrTree::BiThrTree()
{
    m_root=createBiTree();
    m_root=inThreading_addHeader(m_root);
}

BiThrTree::~BiThrTree()
{
    deleteBiThrTree(m_root);
}

//构造二叉树
BiThrNode *BiThrTree::createBiTree()
{
    char ch;
    QTextStream in(stdin);
    in>>ch;

    BiThrNode *node;
    if(ch=='#')
        node=nullptr;
    else
    {
        node=new BiThrNode;
        node->data=ch;
        node->rTag=Link;
        node->lTag=Link;
        qDebug()<<"输入左节点:";
        node->lchild=createBiTree();
        qDebug()<<"输入右节点:";
        node->rchild=createBiTree();
    }
    return node;
}

void BiThrTree::deleteBiThrTree(BiThrNode *node)
{
    if(!node)
        return;

    deleteBiThrTree(node->lchild);
    deleteBiThrTree(node->rchild);
    delete node;
    node=nullptr;
}

BiThrNode *BiThrTree::getRoot()
{
    return m_root;
}

//中序遍历线索化二叉树
void BiThrTree::inThreading(BiThrNode *currentNode)
{
    if(!currentNode)
        return;

    inThreading(currentNode->lchild);
    if(!currentNode->lchild)
    {
        currentNode->lTag=Thread;
        currentNode->lchild=pre;
    }
    if(!pre->rchild)
    {
        pre->rTag=Thread;
        pre->rchild=currentNode;
    }
    pre=currentNode;
    inThreading(currentNode->rchild);
}

BiThrNode *BiThrTree::inThreading_addHeader(BiThrNode *root)
{
    //[1] 实例化并添加一个头结点
    BiThrNode *header=new  BiThrNode;
    header->lTag=Link;
    header->rTag=Thread;
    header->rchild=header;
    //[1]

    if(!root)
        header->lchild=header;
    else
    {
        header->lchild=root;
        pre=header;
        inThreading(root);
        header->rchild=pre;//头结点的右指针指向中序变量的最后一个结点
        //线索二叉树中的最后一个结点的rchild指向头结点
        pre->rTag=Thread;
        pre->rchild=header;
    }
    return  header;
}

//线索二叉树中序正向遍历(从头向尾遍历)
void BiThrTree::Thr_InOrder_Forward(BiThrNode *header)
{
    BiThrNode *p;//指向当前位置的指针

    p=header->lchild;
    while(p!=header)
    {
        while(p->lTag==Link)//找到线索二叉树中序遍历的第一个结点
            p=p->lchild;
        qDebug()<<p->data;
        while(p->rTag==Thread&&p->rchild!=header)
        {
            //表明此时rchild指针没有指向一棵子树 二是存放的是后继节点
            p=p->rchild;
            qDebug()<<p->data;
        }
        p=p->rchild;
    }
}

//线索二叉树中序反向遍历(从尾向头遍历)
void BiThrTree::Thr_InOrder_Reverse(BiThrNode *header)
{
    BiThrNode *rp;//指向当前位置的指针
    rp=header->rchild;
    while(rp!=header)
    {
        while(rp->rTag==Link)
        {
           rp=rp->rchild;//妈蛋 竟然没有给rp重新赋值
        }
        qDebug()<<rp->data;
        while (rp->lTag==Thread&&rp->lchild!=header)
        {
            rp=rp->lchild;
            qDebug()<<rp->data;
        }
        rp=rp->lchild;
    }
}


main函数:

#include <QCoreApplication>
#include <QDebug>
#include <QObject>
#include "bithrtree.h"
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

     qDebug()<<"Input character:";
     BiThrTree biThrTree;
     qDebug()<<"Thr_InOrder_Forward:";
     biThrTree.Thr_InOrder_Forward(biThrTree.getRoot());
     qDebug()<<"Thr_InOrder_Reverse:";
     biThrTree.Thr_InOrder_Reverse(biThrTree.getRoot());

    return a.exec();
}


结果:



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值