线索二叉树是一种不用设栈就可以遍历的二叉树, 如果在某个程序中所用的二叉树需经常遍历或者查找结点在遍历所得到线性序列中的前驱和后继,则应采用线索链表作存储结构。
怎么样才能在遍历的时候不需要设栈呢? 这就需要利用二叉链表中的空链域。若结点有左子树,则其lchild域指示其左孩子,否则令lchild域指示其前驱; 若结点有右子树,则其rchild域指示其右孩子,否则rchild域指示其后继。
二叉树的二叉线索存储表示:
typedef enum PointerTag{Link, Thread};
typedef struct BiThrNode
{
TElemType data;
struct BiThrNode *lchild, *rchild;
PointerTag LTag, RTag;
}BiThrNode, *BiThrTree;
当LTag等于0的时候lchild是指针(指示结点的左孩子),
当LTag等于1的时候lchild是索引(指示结点的前驱)。
当RTag等于0的时候rchild是指针(指示结点的右孩子),
当RTag等于1的时候rchild是索引(指示结点的后继)。
有这样的结构的二叉树,称为线索二叉树。
下面是中序线索化二叉树和遍历线索二叉树的算法实现。
二叉树线索化时增加一个头结点,左孩子指向需要线索化的根节点, 右孩子指向中序遍历的时访问的最后一个结点。
如果是一颗空树的时候,左指针和右指针都回指向头结点。
//BiThrTree.h
#define STACK_INIT_SIZE 100
#define STACKINCREMENT 10
#define OK 1
#define OVERFLOW -2
#define Status bool
#define TRUE 1
#define FALSE 0
#define ERROR 0
typedef enum PointerTag{Link, Thread};
typedef char TElemType;
typedef struct BiThrNode
{
TElemType data;
struct BiThrNode *lchild, *rchild;
PointerTag LTag, RTag;
}BiThrNode, *BiThrTree;
void CreateTree(BiThrTree & T);
Status InOrderThreading(BiThrTree &Thrt, BiThrTree T);
void InThreading(BiThrTree T);
Status InOrderTraverse_Thr(BiThrTree Thrt, Status (*visit)(TElemType e));
//BiThrTree.cpp
#include "BiThrTree.h"
#include <stdlib.h>
#include <stdio.h>
BiThrTree pre; //始终指向刚刚访问过的结点。
void InThreading(BiThrTree 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);
}
}
/*
Thrt表示线索化后的二叉树,T表示要进行线索化的二叉树
*/
Status InOrderThreading(BiThrTree &Thrt, BiThrTree T)
{
Thrt = (BiThrTree)malloc(sizeof(BiThrNode));
if (!Thrt) exit(OVERFLOW);
Thrt->LTag = Link; Thrt->RTag = Thread;
Thrt->rchild = Thrt;
if (!T) Thrt->lchild = Thrt;//如果为空树,则头结点的左右指针都指向头结点。
else
{
Thrt->lchild = T; pre = Thrt;
InThreading(T);
pre->RTag = Thread;
pre->rchild = Thrt;
Thrt->rchild = pre;
}
return OK;
}
Status InOrderTraverse_Thr(BiThrTree T, Status (* visit)(TElemType e))
{
BiThrTree p = T->lchild;
while (p != T)
{
while (p->LTag == Link)
{
p = p->lchild;
}
visit(p->data);
while (p->RTag == Thread && p->rchild != T)
{
p = p->rchild;
visit(p->data);
}
p = p->rchild;
}
return OK;
}
void CreateTree(BiThrTree &T)
{
char ch;
scanf("%c", &ch);
if (ch == ' ') T = NULL;
else
{
T = (BiThrTree)malloc(sizeof(BiThrNode));
if (!T) exit(OVERFLOW);
T->data = ch;
T->LTag = Link;
T->RTag = Link;
CreateTree(T->lchild);
CreateTree(T->rchild);
}
}