#include<stdio.h>
#include<stdlib.h>
#define Maxsize 10
typedef char ElemType;
//线索存储标志为(枚举类型)
//Link==0:表示指向左右孩子的指针
//Thread==1:表示指向前驱后继的线索
typedef enum{Link,Thread} PointerTag;
//线索二叉树
typedef struct BiTNode
{
ElemType data;
struct BiTNode *lchild,*rchild;
PointerTag ltag,rtag; //枚举类型变量
}BiTNode,*BiTree;
//全局变量,始终指向刚刚访问过的结点
BiTree pre;
//前序输入创建一个二叉树
CreateBiTree(BiTree *T)
{
char c;
scanf("%c",&c);
//空格表示虚结点,如果不是虚结点,则建立新结点。
if(c==' ')
{*T=NULL;}
else
{
*T=(BiTree)malloc(sizeof(BiTNode));
(*T)->data=c;
(*T)->ltag=Link;
(*T)->rtag=Link;
CreateBiTree(&(*T)->lchild);//创建左子树
CreateBiTree(&(*T)->rchild);//创建右子树
}
}
//中序遍历线索化过程 (未给pre赋值)
MidOrder(BiTree T)
{
if(T)
{ MidOrder(T->lchild);//递归左孩子线索化
//结点处理
if(!T->lchild) //该结点没有左孩子,结点的ltag为Threat(线索),且lchild指向上一个访问的结点
{
T->ltag=Thread;
T->lchild=pre;
}
if(!pre->rchild)
{
pre->rtag=Thread;
pre->rchild=T;
}
pre=T;
MidOrder(T->rchild);//递归右孩子线索化
}
}
//中序遍历线索化完整实现
MidOrderReading(BiTree *p,BiTree T)
{
*p=(BiTree)malloc(sizeof(BiTNode));
(*p)->ltag=Link;
(*p)->rtag=Thread;
(*p)->rchild=*p;
if(!T)
{
(*p)->lchild=*p;
}
else
{
(*p)->lchild=T;
pre=(*p);
MidOrder(T);
pre->rchild=*p;
pre->rtag=Thread;
}
}
//查找某节点的前驱结点
BiTNode* FindPrior(BiTNode *q)
{
pre=q->lchild;
if(pre->ltag==Link)//有左孩子 ,查找中序遍历其左子树时访问的最后一个结点
{
while(pre->rtag==Link )//沿pre右子树右指针向下查找,直到右结点rtag为Threat为止
pre=pre->rchild;
}
return pre;
}
原理如下
int main()
{
BiTree p,T=NULL;
CreateBiTree(&T);
MidOrderReading(&p,T);
printf("%c",FindPrior(T)->data);
}
示例:输入:
得到的中序序列为
得到的线索二叉树如图示
若使用查找函数FindPrior(BiTNode *q)
则返回该结点的中序遍历的上一个结点,如查找A结点的前驱结点为D