/*
二叉树的链式存储中不能够得到一个结点的前驱和后继的信息
这些信息只有在遍历的动态过程中才能得到。
为了保存这种在遍历中也可得到的信息
最简单的方法就是为每一个结点增加两个指针域;fwd和bkwd
注:此处的前驱和后继为:遍历过程中的前驱和后继(误解:该结点的父节点和子节点)
另外在n个结点中,必存在n+1个空链域(因为满二叉树总结点树2n+1,个人理解的)
由此设想能否利用这些空链域来存放结点的前驱和后继的信息:
试做一下规定:
如果有左孩子:lchild就存左孩子,否则lchild存前驱
如果有右孩子:rchild就存右孩子,否则rchild存后继
增加两个标志域;
lchild LTag date RTag rchild
LTag=0 lchild 存左孩子
=1 lchild 存前驱
RTag=0 rchild 存右孩子
=1 rchild 存后继
这样的存储结构:叫做线索链表
直线前驱和后继的指针,叫做线索
加上线索的二叉树叫做;线索二叉树
*/
//二叉树的二叉先说存储表示
#include "stdio.h"
#include "stdlib.h"
#include "malloc.h"
typedef enum PointerTag{Link,Thread};//Link==0 指针, Thread ==1 线索
typedef char TElemType;
typedef struct BiThrNode
{
char data;
struct BiThrNode *lchild,*rchild;
PointerTag LTag,RTag;
}BiThrNode,*BiThrTree;
void CreateBiTree(BiThrTree *T)//按先序遍历创建二叉树 T为bt的地址 *T为bt
{
TElemType ch;
scanf("%c",&ch);
//ch = getchar();
if(ch=='#'){
*T = NULL;
}else
{
*T= (BiThrTree)malloc(sizeof(BiThrNode));
if((*T)==NULL)//和(!(*T))一样都是T为空时 表达式true,执行
{
exit(1);
}
else
{
(*T)->data = ch;
CreateBiTree(&((*T)->lchild)); //bt->lchild是一个指针,参数要为指针的地址,故取地址
if((*T)->lchild)
{
(*T)->LTag=Link;
}
CreateBiTree(&((*T)->rchild));
if((*T)->rchild)
{
(*T)->RTag=Link;
}
}
}
}
/*
中序遍历线索化的递归函数代码
*/
BiThrTree pre ;
void InThreading(BiThrTree T)
{
if(T)
{
InThreading(T->lchild);//递归左子树线索化
/
if(!T->lchild)//如果没有左孩子
{
T->LTag=Thread;//前驱线索
T->lchild = pre;
}
if(!pre->rchild)//如果没有右孩子 (此处判断的当前结点的左孩子和,上面判断的没有右孩子为同一结点,因为当当前结点没有左孩子时:该结点被改变所以用pre保存当前结点)
{
pre->RTag = Thread;//后继线索
pre->rchild = T;//前驱右孩子指针指向后继(当前结点T)
}
pre = T; //保存pre指向T的前驱
/
InThreading(T->rchild);//递归右子树线索化
}
}
void InOrderThreading(BiThrTree *Thrt,BiThrTree T)
{
(*Thrt)=(BiThrTree)malloc(sizeof(BiThrNode));
if((*Thrt)==NULL)
{
return ;
}
/*if(!((*Thrt)=(BiThrTree)malloc(sizeof(BiThrNode))))
exit(1);
*/
(*Thrt)->LTag = Link; //建立结点
(*Thrt)->RTag = Thread;
(*Thrt)->rchild = (*Thrt);//右指针回指
if(T==NULL)
{
(*Thrt)->lchild = (*Thrt);//为空,左指针回指
}
else
{
(*Thrt)->lchild =T;
pre = (*Thrt);
InThreading(T); //中序遍进行中序线索化
//最后一个节点线索化
pre->rchild = (*Thrt);
pre->RTag = Thread;
(*Thrt)->rchild = pre;
}
}
//遍历二叉树
void InOrderTraverse_Thr(BiThrTree T)
{
//T指向头节点,头节点的左链lchild指向根节点
//中序遍历二叉树T的非递归算法
BiThrTree p;
p = T->lchild;
while(p!=T)
{
while(p->LTag==Link)//LTag==0时循环到中序序列第一个结点
p=p->lchild;
printf("%c",p->data);
while(p->RTag==Thread&&p->rchild!=T)
{
p=p->rchild;
printf("%c",p->data);
}
p=p->rchild;
}
return ;
}
void main()
{
BiThrTree T,H; /*ABDH#K###E##CFI###G#J##*/
//创建二叉树
CreateBiTree(&T);
InOrderThreading(&H,T);
printf("中序遍历(输出)线索二叉树:\n");
InOrderTraverse_Thr(H);//注此处参数为 H非T
printf("\n");
}