定义
在二叉树的结点上加上线索的二叉树称为线索二叉树,对二叉树以某种遍历方式(如先序、中序、后序或层次等)进行遍历,使其变为线索二叉树的过程称为对二叉树进行线索化。
优势
1.利用线索二叉树进行中序遍历时,不必采用堆栈处理,速度较一般二叉树的遍历速度快,且节约存储空间。
2.任意一个结点都能直接找到它的前驱和后继结点。
不足
1.结点的插入和删除麻烦,且速度也较慢。
2.线索子树不能共用。
定义类型
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAXSIZE 100 /* 存储空间初始分配量 */
/* Status是函数的类型,其值是函数结果状态代码,如OK等 */
typedef int Status;
typedef char CElemType;
/* 字符型以空格符为空 */
CElemType Nil='#';
/* Link==0表示指向左右孩子指针, */
/* Thread==1表示指向前驱或后继的线索 */
typedef enum {Link,Thread} PointerTag;
/* 线索二叉树存储结点结构*/
typedef struct BiThrNode {
//数据
CElemType data;
//左右孩子指针
struct BiThrNode *lchild, *rchild;
//左右标记
PointerTag LTag;
PointerTag RTag;
} BiThrNode, *BiThrTree;
构造二叉树
Status CreateBiThrTree(BiThrTree *T) {
CElemType h;
//scanf("%c",&h);
//获取字符
h = str[indexs++];
if (h == Nil) {
*T = NULL;
}else{
*T = (BiThrTree)malloc(sizeof(BiThrNode));
if (!*T) {
exit(OVERFLOW);
}
//生成根结点(前序)
(*T)->data = h;
//递归构造左子树
CreateBiThrTree(&(*T)->lchild);
//存在左孩子->将标记LTag设置为Link
if ((*T)->lchild) (*T)->LTag = Link;
//递归构造右子树
CreateBiThrTree(&(*T)->rchild);
//存在右孩子->将标记RTag设置为Link
if ((*T)->rchild) (*T)->RTag = Link;
}
return OK;
}
中序遍历,线索化的递归方法
BiThrTree pre; /* 全局变量,始终指向刚刚访问过的结点 */
/* 中序遍历进行中序线索化*/
void InThreading(BiThrTree p){
/*
InThreading(p->lchild);
.....
InThreading(p->rchild);
*/
if (p) {
//递归左子树线索化
InThreading(p->lchild);
//无左孩子
if (!p->lchild) {
//前驱线索
p->LTag = Thread;
//左孩子指针指向前驱
p->lchild = pre;
} else {
p->LTag = Link;
}
//前驱没有右孩子
if (!pre->rchild) {
//后继线索
pre->RTag = Thread;
//前驱右孩子指针指向后继(当前结点p)
pre->rchild = p;
} else {
pre->RTag = Link;
}
//保持pre指向p的前驱
pre = p;
//递归右子树线索化
InThreading(p->rchild);
}
}
中序遍历,线索化的入口方法
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);
//最后一个结点rchil 孩子
pre->rchild = *Thrt;
//最后一个结点线索化
pre->RTag = Thread;
(*Thrt)->rchild = pre;
}
return OK;
}
中序遍历
Status InOrderTraverse_Thr(BiThrTree T){
BiThrTree p;
p = T->lchild; /* p指向根结点 */
while (p != T) { /* 空树或遍历结束时,p==T */
while (p->LTag == Link)
p = p->lchild;
if (!visit(p->data)) /* 访问其左子树为空的结点 */
return ERROR;
while(p->RTag==Thread && p->rchild!=T) {
p = p->rchild;
visit(p->data); /* 访问后继结点 */
}
p = p->rchild;
}
return OK;
}
网友评论