A与B的对话之线索二叉树
A:什么是线索二叉树?
B:先别着急,你知道二叉树的定义的存储结构是什么吗?
A:当然知道,就是包含一个值域和两个指针域的结构体,下图所示
typedef struct node
{
char data;
struct node *left,*right;
}Tree
B:是的,是这样的,我们可以从代码中看出,我们可以通过left和right指针来找到一个结点的左右孩子,对吗?那如果我们想要找到一个结点的前驱和后继该怎么办呢?
A:很容易找到左右孩子,嗯?前序和后继?这个是什么意思?
B:我们知道一个树有三种遍历,前后中,比如一个树的前序遍历是ABC,我们很容易看出B的前驱结点时A,B的后继结点是C,当我们遍历整个二叉树时,很容易找出某个结点的前驱和后继,那么如果我需要直接让你用代码找出一个结点的前驱和后继,你该怎么办呢?
A:添加新的指针吗?
B:不用不用,你想想我们建立一棵有n个结点的树时,创建了多少指针?
A:一个结点两个指针,当然是2n个指针
B:我们一共用了多少个指针呢?
A:n个结点的二叉树的一共有n-1条分支,那么我们就用了n-1个指针,还有2n-(n-1)个指针没有使用
B:对了,我们就可以利用着n+1个指针来指向一个结点的前驱和后继,而且还利用了空间
A:我有点糊涂了,那应该怎么做呢?
B:因为我们的结点本生就具有两个指针,我们如何知道它的左右孩子是指向前驱还是后继呢?我们在原有的基础上,加上ltga和rtag来判断左右指针的指向
ltag==0时代表该结点的left指针指向的是左孩子
ltag==1时代表该结点的left指针指向的是前驱结点
同理可知rtag
A:我明白了!那我们该如何实现呢
B:我们在遍历二叉树的时候就会知道结点的前驱,那时候我们就可以给ltag和rtag进行赋值
A:我通过中序遍历来给ltag和rtag赋值
#include <iostream>
#include<stdlib.h>
using namespace std;
typedef struct node
{
char data;
struct node *left,*right;
int ltag,rlag;
}ThreadTree;//线索二叉树
ThreadTree *create()//递归创建二叉树
{
ThreadTree *t=(ThreadTree *)malloc(sizeof(ThreadTree));
char a;
cin>>a;
if(a=='#')
t=NULL;
else{
t->data=a;
t->left=t->right=NULL;
t->left=create();
t->right=create();
}
return t;
}
void Zhongxu(ThreadTree *t)//中序线索二叉树
{
ThreadTree *pre;//代表后继
if(t)
{
Zhongxu(t->left);
if(t->left==NULL)//左是前驱
{
t->ltag=1;
t->left=pre;
}
if(pre->right==NULL)//右是后继
{
pre->rlag=1;
pre->right=t;
}
pre=t;
cout<<t->data;
Zhongxu(t->right);
}
}
int main()
{
ThreadTree *t;
t=create();//创建二叉树
Zhongxu(t);//中序遍历二叉树
}
A:这就是线索二叉树的过程,现在你明白什么是线索二叉树了嘛
B:明白了!线索二叉树就是利用二叉树空闲的指针,将它指向结点的前驱后者后继,这样就很快可以找到一个结点的前驱和后继
A:Yes,就是这样。不要忘记了,线索二叉树有三种结构哦~

浙公网安备 33010602011771号