#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_PreThreadBiTree(ThreadBiTree * T); // 建立先序线索二叉树
void PreThread_BiTree(ThreadBiTree * T, ThreadBiTree * pre);// 先序遍历线索化二叉树
ThreadBiTree Get_Next(ThreadBiTree T); // 获取先序线索二叉树的后继结点
void PreTraverse_ThreadBiTree(ThreadBiTree T); // 先序遍历线索二叉树
bool Destroy_PreThreadBiTree(ThreadBiTree T); // 销毁线索二叉树
int main()
{
ThreadBiTree T;
printf("请输入根结点:");
Creat_BiTree(&T);
Creat_PreThreadBiTree(&T);
printf("\n");
printf("先序遍历输出线索二叉树:");
PreTraverse_ThreadBiTree(T);
printf("\n");
if(Destroy_PreThreadBiTree(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_PreThreadBiTree(ThreadBiTree * T)
{
ThreadBiTree pre = NULL;
if(!(*T))
return;
else
{
PreThread_BiTree(T, &pre);
pre->rtag = 1;
pre->rchild = NULL;
return;
}
}
void PreThread_BiTree(ThreadBiTree * T, ThreadBiTree * pre)
{
if(!(*T))
return;
if((*T)->lchild == NULL)
{
(*T)->ltag = Thread;
(*T)->lchild = *pre;
}
if((*pre) != NULL && (*pre)->rchild == NULL ) // 注意这两玩意的顺序哈
{
(*pre)->rtag = Thread;
(*pre)->rchild = *T;
}
*pre = *T; // 更新指向前趋结点的指针
if((*T)->ltag == Link)
PreThread_BiTree(&(*T)->lchild, pre);// 递归线索化左子树
/*
在前面判断左孩子是否为空的时候,假设左孩子为空,这时已经改变了左孩子指针域的值,
因为左孩子为空,这时再对其进行递归遍历则毫无意义,进行递归遍历的前提是左孩子必须存在,
否则会出现段错误
*/
PreThread_BiTree(&(*T)->rchild, pre);// 递归线索化右子树
}
ThreadBiTree Get_Next(ThreadBiTree T) // 寻找下一个结点
{
if(!T)
return NULL;
else
{
if(T->rtag == Thread || T->ltag == Thread)
return T->rchild;
else
return T->lchild;
/*
if(T->rtag == Thread) 该结点为左孩子结点
return T->rchild;
else
{
if(T->ltag == Link) 该结点为根结点
return T->Lchild;
else
return T->rchild;
}
*/
}
}
void PreTraverse_ThreadBiTree(ThreadBiTree T)
{
ThreadBiTree p = T; // 获取先序线索二叉树的第一个结点
while(p)
{
printf("%3c",p->data); // 先序遍历输出前序线索二叉树
p = Get_Next(p);
}
return;
}
bool Destroy_PreThreadBiTree(ThreadBiTree T)
{
ThreadBiTree p = T;
while(p)
{
ThreadBiTree q = Get_Next(p);
free(p);
p = q;
}
T = p = NULL;
return true;
}