#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
typedef char DataType;
// 标志域利用枚举常量来实现
typedef enum
{
Link, // Link(0)—指针
Thread // Thread(1)—线索
}flag;
typedef struct TNode
{
DataType data; // 数据域
struct TNode * lchild; // 左指针域
struct TNode * rchild; // 右指针域
flag ltag,rtag; // flag == 0——指向左、右孩子,flag == 1——指向前驱、后继
}ThreadTNode,*ThreadBiTree;
void Creat_BiTree(ThreadBiTree * T); // 建立二叉树
void Creat_InThreadBiTree(ThreadBiTree * T); // 建立中序线索二叉树
void InThread_BiTree(ThreadBiTree * T, ThreadBiTree * pre); // 中序遍历线索化二叉树
ThreadBiTree Get_First(ThreadBiTree T); // 获取线索二叉树中的第一个结点
ThreadBiTree Get_Next(ThreadBiTree T); // 获取线索二叉树的后继结点
void InTraverse_ThreadBiTree(ThreadBiTree T); // 中序遍历线索二叉树
bool Destroy_InThreadBiTree(ThreadBiTree T); // 销毁线索二叉树
int main()
{
ThreadBiTree T;
printf("请输入根结点:");
Creat_BiTree(&T);
Creat_InThreadBiTree(&T);
printf("\n");
printf("中序遍历输出线索二叉树:");
InTraverse_ThreadBiTree(T);
printf("\n");
if(Destroy_InThreadBiTree(T))
printf("销毁成功!\n");
else
printf("销毁失败!\n");
return 0;
}
void Creat_BiTree(ThreadBiTree * T)
{
char ch;
fflush(stdin);
scanf("%c",&ch);
if(ch == '#')
{
*T = NULL;
return;
}
else
{
*T = (ThreadBiTree)malloc(sizeof(ThreadTNode));
(*T)->data = ch;
printf("请输入%c的左孩子:",ch);
Creat_BiTree(&(*T)->lchild);
printf("请输入%c的右孩子:",ch);
Creat_BiTree(&(*T)->rchild);
}
}
void Creat_InThreadBiTree(ThreadBiTree * T)
{
ThreadBiTree pre = NULL;
if(!(*T))
return;
else
{
InThread_BiTree(T, &pre);
pre->rtag = 1;
pre->rchild = NULL;
return;
}
}
void InThread_BiTree(ThreadBiTree * T, ThreadBiTree * pre)
{
if(!(*T))
return;
InThread_BiTree(&(*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; // 更新指向前趋结点的指针
InThread_BiTree(&(*T)->rchild, pre);// 递归线索化右子树
}
ThreadBiTree Get_First(ThreadBiTree T)
{
if(!T)
return NULL;
else
{
while(T->ltag == Link) // 中序遍历:如果左标志域为0,表明该结点存在左孩子,则一直遍
// 历到最左边的左孩子结点(直到左标志域为1)
T = T->lchild;
return T; // 当且仅当左标志域为1时,表明该结点为子树的最左边结点,同时
// 也是线索二叉树的第一个结点
}
}
ThreadBiTree Get_Next(ThreadBiTree T) // 寻找下一个结点
{
if(!T)
return NULL;
else
{
if(T->rtag == Thread) // 如果右标志域为1,表明该结点无右孩子,则直接返回
// 该结点的后继结点
{
return T->rchild;
}
else
return Get_First(T->rchild);// 如果右标志域为0,说明该结点存在右孩子,这时调用
// Get_First()函数获取右孩子所在子树的第一个结点
}
}
void InTraverse_ThreadBiTree(ThreadBiTree T)
{
ThreadBiTree p = Get_First(T); // 获取中序线索二叉树的第一个结点
while(p)
{
printf("%3c",p->data); // 中序遍历输出中序线索二叉树
p = Get_Next(p); // 寻找该结点的下一个结点
}
return;
}
bool Destroy_InThreadBiTree(ThreadBiTree T)
{
ThreadBiTree p = Get_First(T);
while(p)
{
ThreadBiTree q = Get_Next(p);
free(p);
p = q;
}
T = p = NULL;
return true;
}

