#include <stdio.h>
#include <stdlib.h>
typedef enum{LINK=0,THREAD} PointerTag;//为0表示右左右孩子,为1表示没有,则为线索
struct BiThrNode
{
char data;//节点存储的数据
BiThrNode* lchild,*rchild;//左右孩子
PointerTag LTag;//坐标志,标志是否为孩子或是线索
PointerTag RTag;//右标志,标志是否为孩子或是线索
};
//先用先序创建的方法创建一个二叉树
//声明函数
void InThreading(BiThrNode* T);
//中序遍历线索化
BiThrNode *pre=NULL;//指向前一个节点
//这个是将头结点与我们的线索二叉树连起来 T是二叉树的根节点,Head是头结点,我们用一个指针的引用作为参数,这个效果同二级指针,可以改变指针的地址
void InOrderThreading(BiThrNode*T ,BiThrNode* & Head)
{
//Head指针已经被改变
Head=(BiThrNode*)malloc(sizeof(BiThrNode));
if(Head)
{
Head->LTag=LINK;//让左节点标志为LINK
Head->RTag=THREAD;
Head->rchild=Head;
}
if(T)
{
Head->lchild=T;
pre=Head;//让第一次的访问节点设置为头结点
InThreading(T);
//线索化完头pre已经指向了最右端的子节点
pre->RTag=THREAD;
//Head=PtMP;
pre->rchild=Head;
Head->rchild=pre;
}else{
Head->lchild=Head;
}
}
//中序遍历线索二叉树,T表示头结点
void InOrderTraverse_THR(BiThrNode* T)
{
BiThrNode* P=T->lchild;//让P指向根节点
while(P!=T)//当P==T时表明线索二叉树已经遍历完
{
while(P->LTag==LINK)
{
P=P->lchild;//一直找到最左端的子节点
}
printf("%c",P->data);//打印出数据
while(P->RTag== THREAD&&P->rchild!=T)//注:P->rchild==T表示P指向了最右端的一个节点
{
//表明P的右子树不存在,所以我们得到指向指向后驱节点
P=P->rchild;
printf("%c",P->data);//打印后驱节点的值
}
//开始访问P的右子节点
P=P->rchild;
}
}
//创建二叉树
void Create_BiThrNode_ByPrev_2(BiThrNode** T)
{
*T=(BiThrNode*)malloc(sizeof(BiThrNode));
if(*T==NULL) exit(0);//开辟内存错误
char ch;
scanf("%c",&ch);
if(ch=='#')
{
*T=NULL;
}else{
(*T)->data=ch;
(*T)->LTag=LINK;//这一这个标志必须指定,要不然程序就会输不出所有结果(我为了找个问题,找了一个多小时。。。心酸。。)
(*T)->RTag=LINK;
Create_BiThrNode_ByPrev_2(&(*T)->lchild);
Create_BiThrNode_ByPrev_2(&(*T)->rchild);
}
}
void main()
{
//先生成一个线索二叉树,带头结点
BiThrNode* T=NULL;
printf("请输入一个二叉树的结点,#表示空节点\n");
Create_BiThrNode_ByPrev_2(&T);//先创建一颗二叉树
//PrevOrderTraverse_NODE(T);
BiThrNode* head=NULL;
InOrderThreading(T,head);
printf("\n");
InOrderTraverse_THR(head);
system("pause");
}
//这是一个线索化二叉树,但实际中我们还要真假一个头结点,让这个线索化二叉树连成链表
void InThreading(BiThrNode* T)
{
BiThrNode *p=NULL;
p=T;
if(p)
{
InThreading(p->lchild);//递归左孩子
//程序第一次执行到这时是在最左端的左子树节点
if(!p->lchild)
{
//表明没有左孩子
p->LTag=THREAD;
p->lchild=pre;//指向上一次访问的节点
}
if (!pre->rchild)
{
//表明前驱没有右孩子
pre->RTag=THREAD;//有标志置为THREAD指向后驱节点
pre->rchild=p;//指向后继节点即上一个节点
}
pre=p;//保持pre指向前一个节点
InThreading(p->rchild);//递归右子树
}
}
上述代码注释的很详细,线索二叉树的概念就不做讲解了。(非常感谢数据结构第四版的书关于本算法的讲解)