二叉树的遍历本质上是将一个复杂的非线性结构转换为线性结构,使每个结点都有了唯一前驱和后继(第一个结点无前驱,最后一个结点无后继)。对于二叉树的一个结点,查找其左右子女是方便的,其前驱后继只有在遍历中得到。为了容易找到前驱和后继,有两种方法。一是在结点结构中增加向前和向后的指针fwd和bkd,这种方法增加了存储开销,不可取;二是利用二叉树的空链指针。现将二叉树的结点结构重新定义如下:
lchild ltag data rtag rchild
其中:ltag=0 时lchild指向左子女;
ltag=1 时lchild指向前驱;
rtag=0 时rchild指向右子女;
rtag=1 时rchild指向后继;
线索化过程
源代码如下:
include “stdio.h”
include “stdlib.h”
typedef char ElemType;
typedef enum
{
Link,Thread
}PointTag;
typedef struct BiTNOde
{
ElemType data;
struct BiTNOde *lchild,*rchild;
PointTag ltag,rtag;
}BiTNode,*BiTTree;
BiTTree pre;
//以前序遍历法创建二叉树
void createBiTTree(BiTTree &T)
{
char c;
scanf(“%c”,&c);
if(c == ’ ‘)
{
T = NULL;
}
else
{
T = (BiTTree)malloc(sizeof(BiTNode));
T->data = c;
T->ltag = Link;
T->rtag = Link;
createBiTTree(T->lchild);
createBiTTree(T->rchild);
}
}
void inThreading(BiTTree T)
{
if( T )
{
inThreading(T->lchild); //先序遍历左子树
if(!T->lchild)
{
T->ltag = Thread;
T->lchild = pre;
}
if(!pre->rchild)
{
pre->rtag = Thread;
pre->rchild = T;
}
pre = T;
inThreading(T->rchild); //先序遍历右子树
}
}
void inorderThreading(BiTTree T,BiTTree &p)
{
p = (BiTTree)malloc(sizeof(BiTNode));
if(!p) exit(0);
else
{
p->ltag = Link;
p->rtag = Thread;
p->rchild = p;
}
if(!T)
{
p->lchild = p;
}
else
{
p->lchild = T;
pre = p;
inThreading(T);
pre->rchild = p; /*最后处理工作*/
pre->rtag = Thread;
p->rchild = pre;
}
}
void visit(BiTTree T,ElemType c,int a,int b)//访问
{
c = T->data;
a = T->ltag;
b = T->rtag;
printf(“%d-%c-%d \n”,a,c,b);
}
void inorderTraverse(BiTTree T)//检验
{
ElemType data;
int a,b;
BiTTree p = T->lchild;
while(p != T)
{
while(p->ltag == Link)
p = p->lchild;
visit(p,data,a,b);
while(p->rtag == Thread &&p->rchild != T)//防止进入倒数第二个结点时进入无限循环
{
p = p->rchild,
visit(p,data,a,b);
}
p = p->rchild;
}
}
int main()
{
BiTTree p,T = NULL;
createBiTTree(T);
inorderThreading(T,p);
inorderTraverse(p);//p为第0个结点
return 0;
}
测试结果如下: