#include<stdio.h>
#include<stdlib.h>
#define elemType char
//线索二叉树结点
typedef struct ThreadNode{
elemType data;
struct ThreadNode *lchild,*rchild;
int ltag,rtag;//用来判断一个结点是否有线索
}ThreadNode,*ThreadTree;
//全局变量pre,指向当前结点的前驱
ThreadNode* pre=NULL;
//初始化一颗二叉树
bool initTree(ThreadNode** root,elemType data){
*root=(ThreadNode*)malloc(sizeof(ThreadNode));
if((*root)==NULL){
return false;
}
(*root)->data=data;
(*root)->lchild=NULL;
(*root)->rchild=NULL;
(*root)->ltag=0;
(*root)->rtag=0;
return true;
}
//回收动态开辟的内存
void destroyTree(ThreadNode* root){
if(root!=NULL){
if(root->ltag==0){//确保其左孩子不是线索
destroyTree(root->lchild);
}
if(root->rtag==0){//确保其右孩子不是线索
destroyTree(root->rchild);
}
free(root);
}
}
//给指定结点增添左孩子
bool addLeftNode(ThreadNode* curRoot,elemType data){
ThreadNode* addNode=(ThreadNode*)malloc(sizeof(ThreadNode));
if(addNode==NULL){
return false;
}
addNode->data=data;
addNode->lchild=NULL;
addNode->rchild=NULL;
addNode->ltag=0;
addNode->rtag=0;
curRoot->lchild=addNode;
return true;
}
//给指定结点增添右孩子
bool addRightNode(ThreadNode* curRoot,elemType data){
ThreadNode* addNode=(ThreadNode*)malloc(sizeof(ThreadNode));
if(addNode==NULL){
return false;
}
addNode->data=data;
addNode->lchild=NULL;
addNode->rchild=NULL;
addNode->ltag=0;
addNode->rtag=0;
curRoot->rchild=addNode;
return true;
}
//后序遍历
void postOrder(ThreadNode* curRoot){
if(curRoot!=NULL){
postOrder(curRoot->lchild);
postOrder(curRoot->rchild);
printf("%c ",curRoot->data);
}
}
void visit(ThreadNode* q){
if(q->lchild==NULL){//左子树为空,建立前驱线索
q->lchild=pre;
q->ltag=1;
}
if(pre!=NULL&&pre->rchild==NULL){
pre->rchild=q;
pre->rtag=1;
}
pre=q;
}
//后序遍历二叉树,一边遍历,一边线索化
void postThread(ThreadTree T){
if(T!=NULL){
postThread(T->lchild);//后序遍历左子树
postThread(T->rchild);//后序遍历右子树
visit(T);//线索化根节点
}
}
//后序线索化二叉树T
void createPostThread(ThreadTree T){
pre=NULL;//pre初始化为NULL
if(T!=NULL){//非空二叉树才能线索化
postThread(T);//后序线索化二叉树
if(pre->rchild==NULL){
pre->rtag=1;//处理最后一个结点
}
}
}
ThreadNode* lastBefoRoot(ThreadNode* curRoot){
if(curRoot->rtag==1){//表示右孩子被线索化,没有右孩子
return curRoot->lchild;
}
else return curRoot->rchild;
}
//根据后序线索二叉树找到指定结点的前驱结点
ThreadNode* findBefore(ThreadNode* root){
if(root!=NULL){
if(root->ltag==0) return lastBefoRoot(root);
else return root->lchild;
}
}
//利用后序线索二叉树,逆序输出,非递归
void RevPostOrder(ThreadNode* root){
for(ThreadNode* cur=root;cur!=NULL;cur=findBefore(cur)){
printf("%c ",cur->data);
}
}
int main(){
ThreadTree root;
initTree(&root,'A');
addLeftNode(root,'B');
addRightNode(root,'C');
addRightNode(root->lchild,'D');
addLeftNode(root->rchild,'E');
printf("没有线索化的后序遍历:\n");
postOrder(root);
printf("\n");
createPostThread(root);
printf("利用后序线索二叉树逆序输出:\n");
RevPostOrder(root);
printf("\n");
destroyTree(root);
return 0;
}