一颗线索二叉树:
根据下图进行节点的创建:
代码如下:
#include <iostream>
using namespace std;
typedef char ElemType;
typedef struct BiThrNode
{
ElemType data;
int ltag,rtag;
struct BiThrNode *lchild,*rchild;
}BiThrNode,*BiThrTree;
因为普通二叉树有空指针域,所以我们可以利用这些空指针来线索化
1、二叉树的线索化,实质上就是遍历一棵二叉树,在遍历过程中,访问节点的操作是检查当前结点的左右指针域是否为空,如果为空,即将他们改为前驱节点或后继节点的线索。为记录前驱节点,定义pre为全局变量,始终指向当前结点的前驱节点。
定义一个全局变量指向线索二叉树的前驱节点:
BiThrNode *pre;
中序遍历进行线索化:
void InThreading(BiThrTree p)
{
if (p)
{
InThreading(p->lchild);
if (!p->lchild)
{
p->ltag = 1;
p->lchild = pre;
}
if (!pre->rchild)
{
pre->rtag = 1;
pre->rchild = p;
}
pre = p;
InThreading(p->rchild);
}
}
根据下图建立头结点,线索化:
代码如下:
bool InOrderThr(BiThrNode *head,BiThrTree T)
{
head = new BiThrNode;
if (head==NULL)
return false;
head->ltag = 0;
head->rtag = 1;
head->rchild = head;
if (!T)
{
head->lchild = head;
}
else
{
head->lchild = T;
pre = head;
InThreading(T);
pre->rchild = head;
pre->rtag = 1;
head->rchild = pre;
}
return true;
}
对于中序线索二叉树上的任意节点,寻找其中序的前驱节点,有以下两种情况:
1、如果该节点的左标志域为1,那么其左指针所指向的节点便是它的前驱节点。
2、如果该节点的左标志为0,表明该节点有左孩子,根据中序遍历的定义,它的前驱节点是以该节点的左孩子为根节点的子树的最右节点,即沿着其左子树的右指针链向下查找,当某节点的右标志域为1时,它就是所要找的前驱节点。
在中序线索二叉树上查找任意节点的中序前驱节点:
BiThrNode *InPreNode(BiThrNode *p)
{
BiThrNode *pre;
pre = p->lchild;
if (p->ltag!=1)
{
while(pre->rtag == 0)
{
pre = pre->rchild;
}
}
return pre;
}
对于中序线索二叉树上的任意节点,寻找其中序的后继节点,有以下两种情况:
1、如果该节点的右标志域为1,那么其右指针所指向的节点便是它的后继节点。
2、如果该节点的右标志为0,表明该节点有右孩子,根据中序遍历的定义,它的后继节点是以该节点的右孩子为根节点的子树的最左节点,即沿着其右子树的左指针链向下查找,当某节点的左标志域为1时,它就是所要找的后继节点。
在中序线索二叉树上查找任意节点的中序后继节点:
BiThrNode *InpostNode(BiThrNode *p)
{
BiThrNode *post;
post = p->rchild;
if (p->rtag!=1)
{
while(post->ltag==0)
{
post = post->lchild;
}
}
return post;
}
从最后一个节点根据前驱节点进行线索二叉树的遍历:
void InOrderPre(BiThrNode *head)
{
BiThrNode *p;
p = head->rchild;//指向最后一个节点
while(p != NULL && p!=head)
{
cout<<p->data;
p = InPreNode(p);
}
}
从第一个节点根据后继节点进行线索二叉树的遍历:
void InOrderPost(BiThrNode *head) {
BiThrNode *p;
p = head->lchild;
while (p->ltag != 1) {
p = p->lchild;
}
while (p != NULL && p != head) {
cout << p->data;
p = InPostNode(p);
}
}
完整代码如下:
#include <iostream>
using namespace std;
typedef char ElemType;
typedef struct BiThrNode {//节点的创建
ElemType data;
int ltag, rtag;
struct BiThrNode *lchild, *rchild;
} BiThrNode, *BiThrTree;
BiThrNode *pre;//定义一个全局变量指向线索二叉树的前驱节点
void InThreading(BiThrTree &p) {
if (p) {
InThreading(p->lchild);
if (!p->lchild) {
p->ltag = 1;
p->lchild = pre;
}
if (!pre->rchild) {
pre->rtag = 1;
pre->rchild = p;
}
pre = p;
InThreading(p->rchild);
}
}
bool InOrderThr(BiThrTree &head, BiThrTree T) {
head = new BiThrNode;
if (head == NULL)
return false;
head->ltag = 0;
head->rtag = 1;
head->rchild = head;
if (!T) {
head->lchild = head;
} else {
head->lchild = T;
pre = head;
InThreading(T);
pre->rchild = head;
pre->rtag = 1;
head->rchild = pre;
}
return true;
}
BiThrNode *InPreNode(BiThrNode *p) {
BiThrNode *pre;
pre = p->lchild;
if (p->ltag != 1) {
while (pre->rtag == 0) {
pre = pre->rchild;
}
}
return pre;
}
BiThrNode *InPostNode(BiThrNode *p) {
BiThrNode *post;
post = p->rchild;
if (p->rtag != 1) {
while (post->ltag == 0) {
post = post->lchild;
}
}
return post;
}
void InOrderPre(BiThrNode *head) {
BiThrNode *p;
p = head->rchild;//指向最后一个节点
while (p != NULL && p != head) {
cout << p->data;
p = InPreNode(p);
}
}
void InOrderPost(BiThrNode *head) {
BiThrNode *p;
p = head->lchild;
while (p->ltag != 1) {
p = p->lchild;
}
while (p != NULL && p != head) {
cout << p->data;
p = InPostNode(p);
}
}
void CreateBiTree(BiThrTree &T) {//以先序遍历的方式创建二叉树
char ch;
cin >> ch;
if (ch == '#')
T = NULL;
else {
T = new BiThrNode;
T->data = ch;
T->ltag = 0;
T->rtag = 0;
CreateBiTree(T->lchild);
CreateBiTree(T->rchild);
}
}
int main() {
BiThrTree T;
BiThrNode *head;
CreateBiTree(T);//以先序遍历输入
if (InOrderThr(head, T))
cout << "线索化完成" << endl;
else
cout << "线索化失败" << endl;
cout<<"逆序输出中序遍历: ";
InOrderPre(head);//逆序输出中序遍历
cout << endl;
cout<<"正序输出中序遍历: ";
InOrderPost(head);//正序输出中序遍历
return 0;
}
测试效果图:
测试结果:
本文参考文章地址:
https://blog.csdn.net/g15827636417/article/details/52967949