线索链表的实现 C++代码实现

来源:互联网 发布:totalfinder for mac 编辑:程序博客网 时间:2024/04/29 08:09

/************************线索链表的实现*************************/

#include <iostream>

using namespace std;

 

/*线索链表的类型定义*/

typedef enum{Child,Thread} Flag;

typedef struct ThrNode

{

       chardata;

       structThrNode *lchild,*rchild;

       Flagltag,rtag;

}ThrNode, *ThrTree;

 

 

/*建立中序线索链表*/

 

//先序建立普通的二叉链表

void CreateBiTree(ThrTree &TT)

{

       charch;

       cin>>ch;

       if(ch=='0')

              TT=NULL;

       else

       {

              TT=newThrNode;

              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)

{

       ThrTreepre;

       ThrTreep;

 

       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-Nodehave not Prior-Node!";//p为第一个结点,第一个结点无前驱

              returnNULL;

       }

       elseif(p->ltag==Thread)

              q=p->lchild;//p结点的左指针域为前驱线索,该类结点大多为叶结点

       else

       {

              q=p->lchild;

              while(q->rtag==Child)

                     q=q->rchild;//p结点无前驱线索,则p的前驱应是以p为根结点的左子树的最右下结点,

                                          //该类结点大多为各子树的根结点

       }

       returnq;

}

 

/*在中序线索链表上求结点的后继*/

ThrNode * InThrTreeNext(ThrTree&TT,ThrNode *p)

{

       ThrNode*q;

       if(p->rchild==NULL)

       {

              cout<<"P-Nodehave not Next-Node!";//p为最后一个结点,无后继

              returnNULL;

       }

       elseif(p->rtag==Thread)

              q=p->rchild;//p结点的右指针域为后继线索,该类结点大多为叶结点

       else

       {    

              q=p->rchild;

              while(q->ltag==Child)

                     q=q->lchild;//p结点无后继线索,则p的后继是以p为根结点的右子树的最左下结点,

                                          //这类结点大多是各子树的根结点

       }

       returnq;

}

 

 

/*中序线索链表上的中序遍历*/

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)

              returnNULL;

 

       while(p->ltag==Child)

       p=p->lchild;//先找到第一个结点

 

       while(p->rchild!=NULL&&p->data!=x)

       {

              p=InThrTreeNext(TT,p);

       }

       p=InThrTreePrior(TT,p);

       returnp;

}

void main()

{

       ThrTreeTT;

       CreateInThrTree(TT);

 

       InOrderThrTree(TT);//中序遍历输出结点

      

       //查找某个具体结点的前驱

       charch;

       ThrNode*p;

       cout<<"要查找哪个结点的前驱:";

       cin>>ch;

       p=InThrTreePrior_Ex(TT,ch);

       cout<<"结点 "<<ch<<" 的前驱是"<<p->data<<endl;

}

原创粉丝点击