/************************线索链表的实现*************************/
#include <iostream>
using namespace std;
/*线索链表的类型定义*/
typedef enum{Child,Thread} Flag;
typedef struct ThrNode
{
char data;
struct ThrNode *lchild,*rchild;
Flag ltag,rtag;
}ThrNode, *ThrTree;
/*建立中序线索链表*/
//先序建立普通的二叉链表
void CreateBiTree(ThrTree &TT)
{
char ch;
cin>>ch;
if(ch=='0')
TT=NULL;
else
{
TT=new ThrNode;
TT->data=ch;
TT->ltag=Child;
TT->rtag=Child;//刚开始结点的线索标识都初始化为Child。
CreateBiTree(TT->lchild);
CreateBiTree(TT->rchild);
}
}
//普通的二叉链表进行中序线索化
void InThreading(ThrTree &p,ThrTree &pre)
{
if(p==NULL)
return;
InThreading(p->lchild,pre);//对p结点的左子树线索化
if(!p->lchild)//如果p无左孩子
{
p->ltag=Thread;
p->lchild=pre;//让p的左指针域建立线索,指向前驱
}
if(!p->rchild)//如果p无右孩子
{
p->rtag=Thread;//因为p的后继还不知道,故右指针域先不建立线索
}
if(pre!=NULL)
{
if(pre->rtag==Thread)
pre->rchild=p;//对pre结点加后继线索
}
pre=p;
InThreading(p->rchild,pre);//对p的右子树线索化
}
//调用上面两个函数建立中序线索链表
void CreateInThrTree(ThrTree &TT)
{
ThrTree pre;
ThrTree p;
CreateBiTree(TT);
pre=NULL;//pre初始为空
p=TT;//p初始为头结点
InThreading(p,pre);
}
/*在中序线索链表上求结点的前驱*/
ThrNode * InThrTreePrior(ThrTree &TT,ThrNode *p)
{
ThrNode *q;
if(p->lchild==NULL)
{
cout<<"P-Node have not Prior-Node!";//p为第一个结点,第一个结点无前驱
return NULL;
}
else if(p->ltag==Thread)
q=p->lchild;//p结点的左指针域为前驱线索,该类结点大多为叶结点
else
{
q=p->lchild;
while(q->rtag==Child)
q=q->rchild;//p结点无前驱线索,则p的前驱应是以p为根结点的左子树的最右下结点,
//该类结点大多为各子树的根结点
}
return q;
}
/*在中序线索链表上求结点的后继*/
ThrNode * InThrTreeNext(ThrTree &TT,ThrNode *p)
{
ThrNode *q;
if(p->rchild==NULL)
{
cout<<"P-Node have not Next-Node!";//p为最后一个结点,无后继
return NULL;
}
else if(p->rtag==Thread)
q=p->rchild;//p结点的右指针域为后继线索,该类结点大多为叶结点
else
{
q=p->rchild;
while(q->ltag==Child)
q=q->lchild;//p结点无后继线索,则p的后继是以p为根结点的右子树的最左下结点,
//这类结点大多是各子树的根结点
}
return q;
}
/*中序线索链表上的中序遍历*/
void InOrderThrTree(ThrTree &TT)
{
ThrNode *p;
if(TT==NULL)
return;
p=TT;
while(p->ltag==Child)
p=p->lchild;//先找到第一个结点
cout<<p->data<<" ";
while(p->rchild!=NULL)//此处循环的条件是只要p的右指针域不为空,但最后一个结点的右指针域为空
{
p=InThrTreeNext(TT,p);//把p的后继赋值给p,此处为线索链表遍历的简洁快速之处
cout<<p->data<<" ";
}
cout<<endl;
}
/*实例应用:寻找某个具体结点的前驱*/
ThrNode * InThrTreePrior_Ex(ThrTree &TT,char x)
{
ThrNode *p;
p=TT;
if(TT==NULL)
return NULL;
while(p->ltag==Child)
p=p->lchild;//先找到第一个结点
while(p->rchild!=NULL&&p->data!=x)
{
p=InThrTreeNext(TT,p);
}
p=InThrTreePrior(TT,p);
return p;
}
void main()
{
ThrTree TT;
CreateInThrTree(TT);
InOrderThrTree(TT);//中序遍历输出结点
//查找某个具体结点的前驱
char ch;
ThrNode *p;
cout<<"要查找哪个结点的前驱:";
cin>>ch;
p=InThrTreePrior_Ex(TT,ch);
cout<<"结点 "<<ch<<" 的前驱是 "<<p->data<<endl;
}