#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; // 右孩子指针域
struct TNode * parent; // 双亲指针域
flag ltag,rtag; // flag==0 —指向左、右孩子,flag==1 —指向前驱、后继结点
}ThreadTNode,*ThreadBiTree;
void Creat_BiTree(ThreadBiTree * T); // 建立二叉树
void Creat_PostThreadBiTree(ThreadBiTree * T); // 建立后序线索二叉树
void PostThread_BiTree(ThreadBiTree * T, ThreadBiTree * pre);// 后序线索化二叉树
ThreadBiTree Get_First(ThreadBiTree T); // 获取线索二叉树中的第一个结点
ThreadBiTree Get_Next(ThreadBiTree T); // 获取线索二叉树的后继结点
void PostTraverse_ThreadBiTree(ThreadBiTree T); // 后序遍历线索二叉树
bool Destroy_PostThreadBiTree(ThreadBiTree T); // 销毁线索二叉树
int main()
{
ThreadBiTree T;
printf("请输入根结点:");
Creat_BiTree(&T);
Creat_PostThreadBiTree(&T);
printf("\n");
printf("后序遍历输出线索二叉树:");
PostTraverse_ThreadBiTree(T);
printf("\n");
if(Destroy_PostThreadBiTree(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);
if((*T)->lchild)
(*T)->lchild->parent = *T;
if((*T)->rchild)
(*T)->rchild->parent = *T;
}
}
void Creat_PostThreadBiTree(ThreadBiTree * T)
{
ThreadBiTree pre = NULL;
if(!(*T))
return;
else
{
PostThread_BiTree(T, &pre);
/* pre->rtag = 1;
pre->rchild = NULL;
后序遍历:最后一个结点指向根结点,所以不用修改最后一个结点
的右标志域和右指针域的指向,
*/ return;
}
}
void PostThread_BiTree(ThreadBiTree * T, ThreadBiTree * pre)
{
if(!(*T))
return;
PostThread_BiTree(&(*T)->lchild, pre);// 递归线索化左子树
PostThread_BiTree(&(*T)->rchild, 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; // 更新指向前趋结点的指针
}
ThreadBiTree Get_First(ThreadBiTree T)
{
while(T->ltag == Link)
T = T->lchild;
if(T->rtag == Link)
return Get_First(T->rchild);
return T;
/*
寻找第一个结点:
1.找到最左边的结点
2.判断这个结点是否有右孩子,如果有的话,
继续寻找以右孩子为根结点的子树的最左边的结点,
如果没有,则最左边的结点就是第一个结点
*/
}
ThreadBiTree Get_Next(ThreadBiTree T) // 寻找下一个结点
{
if(T->rtag == Thread)
return T->rchild;
else
{
// 如果是根结点
if(T->parent == NULL)
return NULL;
// 如果是右孩子
else if(T->parent->rchild == T)
return T->parent;
// 如果是左孩子
else
{
if(T->parent->rtag == Thread)
return T->parent;
else
return Get_First(T->parent->rchild);
}
}
/*
寻找后继结点:
1.是根结点:Next == NULL;
2.是左孩子:那么判断双亲右子树是否为空,如果为空,Next == Parent
如果不空,Next == Get_First(T->parent->rchild)
3.是右孩子:Next == Parent
*/
}
void PostTraverse_ThreadBiTree(ThreadBiTree T)
{
ThreadBiTree p = Get_First(T); // 获取后序线索二叉树的第一个结点
while(p)
{
printf("%3c",p->data); // 后序遍历输出前序线索二叉树
p = Get_Next(p);
}
return;
}
bool Destroy_PostThreadBiTree(ThreadBiTree T)
{
ThreadBiTree p = Get_First(T);
while(p)
{
ThreadBiTree q = Get_Next(p);
free(p);
p = q;
}
T = p = NULL;
return true;
}