线索二叉树
前情提要:二叉树的建立与遍历
问题提出:之前的二叉树只能向下走,一条路走到黑,回不去。
思考:如何利用没有孩子节点的节点的结构体内的空指针。
解决:对于上述问题,遇到结构体内存在空指针的情况下,可以用左孩子指针存放这个节点的来路(双亲指针),用右孩子结点存放这个节点的去路(对于不同的遍历方式来说只有中序遍历才可以,而且必须是完全二叉树)。其中来路和去路就是线索。
思路:引入ltag和rtag,tag为1时表明child指针指向的是线索,tag为0时表明child指针指向的是孩子。
#include<stdio.h>
#include<stdlib.h>
typedef char ElemType;
//线索存储标志位
//Link{0}, 表示指向左右孩子的指针
//Thread{1}, 表示指向来源去路的指针
typedef enum {Link, Thread} PointierTag;
typedef struct BiThrTree
{
char data;
struct BiThrTree *lchild, *rchild;
PointierTag ltag, rtag;
}BiThrNode, *BiThrTree;
//全局变量,始终指向上一个访问的节点
BiThrNode *Pre;
//创建树(前序)
void CreateBiThrTree(BiThrTree *T)
{
char c;
scanf("%c",&c);
if(' ' == c)//没有就输入空格
{
*T = NULL;
}
else
{
*T = (BiThrNode*)malloc(sizeof(BiThrNode));
(*T)->data = c;
(*T)->ltag = Link;
(*T)->rtag = Link;
CreateBiThrTree(&(*T)->lchild);
CreateBiThrTree(&(*T)->rchild);
}
}
//访问树的节点
void visit1(char c, int level)
{
printf("%c 位于 %d 层\n",c,level);
}
//访问树的节点
void visit2(char c)
{
printf("%c",c);
}
//将树线索化(中序)
void Threaten(BiThrTree T)
{
if(T)
{
Threaten(T->lchild);
if(!T->lchild)
{
T->ltag = Thread;
T->lchild = Pre;
}
if(!Pre->rchild)
{
Pre->rtag = Thread;
Pre->rchild = T;
}
Pre = T;
Threaten(T->rchild);
}
}
void InOrderThreading(BiThrTree *p, BiThrTree T)
{
*p = (BiThrNode*)malloc(sizeof(BiThrNode));
(*p)->ltag = Link;
(*p)->ltag = Thread;
(*p)->rchild = *p;
if(!T)
{
(*p)->lchild = *p;
}
else
{
(*p)->lchild = T;
Pre = *p;
Threaten(T);
Pre->rchild = *p;
Pre->rtag = Thread;
(*p)->rchild = Pre;
}
}
//遍历树(中序)(递归)
void MedTravelBiThrTree1(BiThrTree T, int level)
{
if(T)
{
MedTravelBiThrTree1(T->lchild, level + 1);
visit1(T->data,level);
MedTravelBiThrTree1(T->rchild, level + 1);
}
}
//遍历树(中序)(循环)
void MedTravelBiThrTree2(BiThrTree T)
{
BiThrTree p;
p = T->lchild;
while(p != T)
{
while(p->ltag == Link)
{
p = p->lchild;
}
visit2(p->data);
while(p->rtag == Thread && p->rchild != T)
{
p = p->rchild;
visit2(p->data);
}
}
}
int main(void)
{
int level = 1;
BiThrTree P, T = NULL;
CreateBiThrTree(&T);
InOrderThreading(&P, T);
MedTravelBiThrTree2(T);
return 0;
}