二叉树的线索化
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
二叉树的线索化:
以二叉链表作为存储结构时,只能找到结点的左、右孩子信
息,而不能直接得到结点在任一序列(先序、中序或后序序列)
中的前驱和后继信息,这种信息只有在遍历的动态过程中才能得
到。为了保存这种在遍历过程中得到的信
息,我们利用二叉链表中的空链域(由于结点没有左子树或右子树),
来存放结点的前驱和后继信息。
作如下规定:
①若结点有左子树,则其lchild 域指示其左孩子,否则令
lchild 域指示其前驱;
②若结点有右子树,则其rchild 域指示其右孩子,否则令
rchild 域指示其后继。
(1)线索链表的结点结构
lchild LTag data RTag rchild
其中: data:数据域;
lchild :左指针域,指向该结点的左孩子;
rchild :右指针域,指向该结点的右孩子;
0lchild域指示结点的左孩子
LTag =
1lchild域指示结点的前驱
0rchild域指示结点的右孩子
RTag =
1rchild域指示结点的后继
请将根据图 1 所示编写一个程序实现构建线索二叉树。
thrt
0 1
bt
0 A 0
0 B 0 0 C 0
1 D 1 0 E 0 1 F 1 1 G 1
1 H 1 0 I 0
1 J 1 1 k 1
图1
#include
#include
#include
#define NULL 0
#define OK 1
#define ERROR 0
typedef enum PointerTag { Link,Thread };//Link==0, 指向孩子; Thread==1, 指向前驱后继 typedef char TElemType;
typedef int Status;
//线索化二叉树的存储结构
typedef struct BiThrNode
{ TElemType data;
struct BiThrNode *lchild,*rchild; // 左孩子与右孩子的指针
PointerTag LTag,RTag; //左右标志域,指示是孩子还是前驱后继
} BiThrNode,*BiThrTree;
//按照先序输入二叉树各个节点,创建原
始二叉树, Status CreateBiTree(BiThrTree&
T) {
#表示空树
char ch;
scanf("%c",&ch);
if('#'==ch) T=NULL;
else
{ T=(BiThrTree )malloc(sizeof(BiThrNode));
if(!T) exit(ERROR);
T->data=ch;
T->LTag=T->RTag=Link;// 建表时初始化都为
CreateBiTree(T->lchild);// 构造左子树CreateBiTree(T->rchild);// 构造右子树Link(
即
0)
}
return OK;
}
BiThrTree pre=NULL; // 定义 pre 为函数 InThreading 的外部变量,使其指向最后一个节点 void InThreading(BiThrTree p); // 函数声明
//中序遍历二叉树,将其线索化,Thrt 指向头结点
Status InOrderThreading(BiThrTree &Thrt,BiThrTree T)
{
Thrt=(BiThrTree)malloc(sizeof(BiThrNode)); // 分配头结点if(!Thrt) exit(ERROR);
//以下三步都是在初始化头结点
Thrt->LTag=Link;// 假设头结点的有右孩子
Thrt->RTag=Thread;// 假设头结点有后继
Thrt->rchild=Thrt;// 暂时使头结点的右指针指向自己
if(!T) Thrt->lchild=Thrt; // 如果树空,就令头结点左指针指向自己
else
{ // 下面先线索头结点
Thrt->lchild=T; // 头结点左指针指向根
pre=Thrt; // 先 pre 指向头指针(也就是根节点的前驱)
//接着线索二叉树
InThreading(T); // 调用函数将T 线索化
//最后线索尾节点
pre->RTag=Thread;// 假设最后一点有后继
pre->rchild=Thrt;// 最后一个点右指针指向头结点
Thrt->rchild=pre;// 头结点的右指针指向最后一个点
}
return OK;
}
//将根为p 的二叉树线索化,千万记住,p 是局部变量,当进入下一次递归时他会屏蔽上一
个p,
//但是上一个p 仍然保留着,等到函数返回时他就又
恢复了上一个
void InThreading(BiThrTree p)
{
p
if(p) // 仅仅当 p 不空时才后继续下面的操作,如果
{ InThreading(p->lchild); // 左子树线索化p 空,那么直接结束,不返回任何值
// 对于当前节点,仅仅处理他与前驱的关系
if(!p->lchild) { p->LTag=Thread; p->lchild=pre; }// 如果当前点左边为空,
指向前驱 if(!pre->rchild) { pre->RTag=Thread; pre->rchild=p; } // 如果上
一点右空,指向后继
pre=p;
InThreading(p->rchild); // 右子树线索化
}
}
//非递归调用,中序线索二叉树 ,T 指向头结点,头结点的 lchild
指向根 Status InOrderTraverse_Thr(BiThrTree T,Status
(*Visit)(TElemType e))
{
BiThrTree p;
p=T->lchild; //p 指向根节点
while(p!=T)