二叉树作为存储结构只能保存其左右孩子结点信息,不能获取结点的前驱和后继信息。同时二叉树结构存在很多个空指针域。一个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 ;//记录刚刚访问过的结点
};
#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();
}
结果: