线索化二叉树的初始化
- 线索化二叉树是根据中序遍历产生的,当一个左右子树节点为空时,使其左子树指向其前驱节点,右子树指向其后继结点
- 为了区分指针到底指向的是前驱后继节点还是左右子树,需要在创建树的节点时再创建两个空间分别用来标记其左右指针指的是什么
typedef enum{LINK,THREAD}TAG;
typedef struct node
{
char data;
struct node*lchild;
struct node*rchild;
TAG rtag;
TAG ltag;
}*PNODE,NODE;
typedef struct tree
{
PNODE root;
char ref;
}TREE;
PNODE create(TREE*t);
void init(TREE* t);
void fronttraverse(PNODE root);
void thread(PNODE t,PNODE *pre);
PNODE first(PNODE root);
PNODE last(PNODE root);
PNODE prio(TREE*t,PNODE cur);
PNODE next(TREE*t,PNODE cur);
void traverse(TREE*t);
int main()
{
TREE tree;PNODE pre=NULL;
init(&tree);
(&tree)->root=create(&tree);
thread((&tree)->root,&pre);
pre->rchild=NULL;
pre->rtag=THREAD;
traverse(&tree);
}
void init(TREE* t)
{
t->root=NULL;
t->ref='#';
}
线索化二叉树的创建
- 需要先按二叉树的创建方法将树结构创建出来,再将其进行线索化
- 线索化是按中序遍历进行的,因此需要按中序的顺序找到最左下的树
PNODE create(TREE*t)
{
char item;
scanf("%c",&item);
if(t->ref==item)
return NULL;
else{
PNODE p=(PNODE)malloc(sizeof(NODE));
p->data=item;
p->rtag=LINK;
p->ltag=LINK;
p->lchild=create(t);
p->rchild=create(t);
return p;
}
}
void thread(PNODE t,PNODE*pre)
{
if(t==NULL)return;
thread(t->lchild,pre);
if(t->lchild==NULL)
{
t->ltag=THREAD;
t->lchild=(*pre);
}
if((*pre)!=NULL&&(*pre)->rchild==NULL)
{
(*pre)->rtag=THREAD;
(*pre)->rchild=t;
}
(*pre)=t;
thread(t->rchild,pre);
}
线索化二叉树的方法实现
1.找寻中序遍历下的第一个元素
PNODE first(PNODE root)
{
PNODE p=root;
while(p->ltag==LINK)
{
p=p->lchild;
}
return p;
}
2.找寻中序遍历下的最后一个元素
PNODE last(PNODE root)
{
PNODE p=root;
while(p->rtag==LINK)
{
p=p->rchild;
}
return p;
}
3.找寻一个节点的在中序下的前驱节点
PNODE prio(TREE*t,PNODE cur)
{
if(t==NULL||cur==NULL)
return NULL;
if(cur->ltag==THREAD)
{
return cur->lchild;
}
return last(cur->lchild);
}
4.找寻一个节点在中序下的后继结点
PNODE next(TREE*t,PNODE cur)
{
if(t==NULL||cur==NULL)
return NULL;
if(cur->rtag==THREAD)
{
return cur->rchild;
}
return first(cur->rchild);
}
5.遍历线索化二叉树
void traverse(TREE*t)
{
for(PNODE p=first(t->root);p!=NULL;p=next(t,p))
{
printf("%c ",p->data);
}
printf("\n");
}
6.查找某个值并返回其节点
PNODE search(TREE*t,char key)
{
for(PNODE p=first(t->root);p!=NULL;p=next(t,p))
{
if(p->data==key)
return p;
}
}
7.找到一个结点的父节点
PNODE parent(TREE*t,PNODE cur)
{
if(t==NULL||cur==NULL)
return NULL
PNODE p;
if(cur->ltag==THREAD)
{
p=cur->lchild;
if(p->rchild==cur)
return p;
}
if(cur->rtag==THREAD)
{
p=cur->rchild;
if(p->lchild==cur)
return p;
}
p=first(cur->lchild);
p=p->lchild;
if(p!=NULL&&p->rchild==cur)
return p;
p=last(cur->rchild);
return p->rchild;
}
总结
- 线索化是对中序、前序、后序遍历而言的,它按这种遍历方式将二叉树存储,可以很方便的找到这种遍历方式下的前驱节点或者后继结点
- 而在遍历二叉树时,也像遍历数组一样用for循环遍历即可,不需要再使用递归了