二叉树的线索化

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 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)

相关文档
最新文档