广义表在学稀疏矩阵之后就应该学的,只是那时觉得看起来晕晕就跳过了,现在回头学了一下,觉得还是不错的一种结构。下面是代码:
文件"glist.h"
#include<iostream>
#include<string>
using namespace std;
enum elemTag {ATOM,LIST};
class GList;
class GLnode
{
private:
elemTag Tag; //标志是原子还是子表 0:原子 1:子表
union
{
char data; //原子结点值域
struct //表结点指针域
{
GLnode *hp;
GLnode *tp;
}ptr;
};
friend class GList;
};
class GList
{
public:
string Decompose(string &str)
{
//将非空串str分割成2部分,hstr为第一个','之前的子串,str为后面的
int n,i,k;
string ch,hstr;
n=str.length();
for(i=0,k=-1;i<n && (ch!="," || k!=0) ;i++)
{
//搜索最外层第一个逗号
ch=str.substr(i,1); //从第i个位置起读1个字符
if(ch=="(")
++k;
else if(ch==")")
--k;
}
if(i<n)
{
hstr=str.substr(1,i-2);//不要左括号,不要逗号,所以是i-2
str="("+str.substr(i,n-i);
}
else
{
hstr=str.substr(1,n-2);
str="";
}
return hstr;
}
/*----------------------------------------------------
/从广义表书写形式串S创建采用头尾链表存储表示的广义表T
/建立广义表头尾结点存储结构的递归定义:
/基本项:当S为空串时,置空广义表
/ 当S为单字符串时,建立原子结点的子表
/递归项:假设sub为脱去S最外层括号的子串,记为"s1,s2,s3,..,sn"
/ 每个si为非空字符串,对每个si建立一个表结点
/--------------------------------------------------------*/
void Create_GList(GLnode *&GL,string S) //创建广义表
{
string hsub;
if(S=="()") //S为空串
{
GL=NULL;
}
else
{
GL=new GLnode;
if(S.length()==1)
{
GL->Tag=ATOM;
GL->data=S[0];
}
else
{
GL->Tag=LIST;
hsub=Decompose(S); //从S中分离出表头串hsub
Create_GList(GL->ptr.hp,hsub);
if(S.empty())
{
GL->ptr.tp=NULL;
}
else
{
Create_GList(GL->ptr.tp,S);
}
}
}
}
int GList_Depth(GLnode *GL) //求广义表深度
{
/*-----------------------------------------
/当广义表为空表时,深度为1,当广义表为原子时
/深度为0,当广义表为广义表时,深度的求法为
/GList_Depth(GL)=1+max{GList_Depth(lsi)}
/-----------------------------------------*/
if(!GL)
return 1;
if(GL->Tag==ATOM)
return 0;
int dep,max;
GLnode *p;
for(max=0,p=GL;p;p=p->ptr.tp)
{
dep=GList_Depth(p->ptr.hp);
if(dep>max)
max=dep;
}
return 1+max;
}
void Copy_GList(GLnode *GL,GLnode *&T) //T复制GL
{
//当表为空时,复制空表,否则先复制表头在复制表尾
if(!GL)
T=NULL;
else
{
T=new GLnode;
T->Tag=GL->Tag;
if(GL->Tag==ATOM)
T->data=GL->data;
else
{
Copy_GList(GL->ptr.hp,T->ptr.hp);
Copy_GList(GL->ptr.tp,T->ptr.tp);
}
}
}
/*-----------------------------------------------
/遍历广义表,如果是空表就输出"()",如果遇到Tag=0
/的结点,则直接输出该结点的值,如果tag=1,说明
/是一个子表,首先输出左括号,然后递归调用输出数据
/元素,并当表尾不空的时候输出逗号,最后输出右括号
/-----------------------------------------------*/
void Traverse_GList(GLnode *L)
{
if(!L)
cout<<"()";
else
{
if(L->Tag==ATOM)
cout<<L->data;
else
{
GLnode *p=NULL;
cout<<'(';
p=L;
while(p)
{
Traverse_GList(p->ptr.hp);
p=p->ptr.tp;
if(p)
cout<<',';
}
cout<<')';
}
}
}
void GetHead(GLnode *GL) //取表头
{
//取广义表第一个元素
cout<<"广义表:";
Traverse_GList(GL);
cout<<endl;
if(!GL || GL->Tag==0 )
cout<<"原子和空表不能去表头"<<endl;
else
{
GLnode *h=GL->ptr.hp;
if(h->Tag==ATOM)
cout<<"表头为:"<<h->data<<endl;
else
{
cout<<"表头为:";
Traverse_GList(h);
cout<<endl;
}
}
}
void GetTail(GLnode *GL) //取表尾
{
//广义表表尾指的是除了第一个元素后所有剩余的元素组成的表
cout<<"广义表:";
Traverse_GList(GL);
cout<<endl;
if(!GL || GL->Tag==0)
cout<<"原子和空表不能取表尾"<<endl;
else
{
GLnode *t;
t=GL->ptr.tp;
cout<<"表尾为:";
Traverse_GList(t);
cout<<endl;
}
}
int Length_GList_1(GLnode *GL) //求表长,非递归
{
//用非递归方式求广义表长度
int len=0;
if(GL && GL->Tag==LIST)
{
while(GL)
{
GL=GL->ptr.tp;
len++;
}
return len;
}
else
return 0;
}
int Length_GList_2(GLnode *GL) //求表长,递归
{
if(!GL)
return 0;
return 1+Length_GList_2(GL->ptr.tp);
}
void Replace_GList(GLnode *p,char x,char y,GLnode *&q) //替换
{
//将广义表p中元素x替换成y,构建新广义表q
if(!p)
q=NULL;
else
{
if(p->Tag==ATOM)
{
q=new GLnode;
q->Tag=ATOM;
q->ptr.hp=NULL;
if(p->data==x)
q->data=y;
else
q->data=p->data;
}
else
{
GLnode *h,*t;
Replace_GList(p->ptr.hp,x,y,h);//递归处理表头得到h
Replace_GList(p->ptr.tp,x,y,t);//递归处理表尾得到t
q=new GLnode;
q->Tag=LIST;
q->ptr.hp=h;
q->ptr.tp=t;
}
}
}
int Is_Same(GLnode *p,GLnode *q)//判断是否相等
{
int flag=1;//1表示相等,0表示不相等
if(p && q)
{
if(p->Tag==ATOM && q->Tag==ATOM)
{
if(p->data!=q->data)
flag=0;
else
flag=1;
}
else if(p->Tag==LIST &&q->Tag==LIST)
flag=Is_Same(p->ptr.hp,q->ptr.hp);
else
flag=0;
if(flag)
flag=Is_Same(p->ptr.tp,q->ptr.tp);
}
else
{
if(p && !q)
flag=0;
if(!p && q)
flag=0;
}
return flag;
}
void Concat_Glist(GLnode *&GL,GLnode *LG) //连接两个广义表
{
GLnode *p=GL;
GLnode *q=p->ptr.tp;
while(q->ptr.tp)
q=q->ptr.tp;
q->ptr.tp=LG;
GL=p;
}
};
测试函数"main.cpp"
#include"glist.h"
int main()
{
GList list;
GLnode *GL=NULL;
string S;
cout<<"输入广义表S:";
cin>>S;
list.Create_GList(GL,S);
cout<<"广义表S的深度为:"<<list.GList_Depth(GL)<<endl;
cout<<"广义表S的长度为:"<<list.Length_GList_1(GL)<<endl;
cout<<"广义表S的长度为:"<<list.Length_GList_2(GL)<<endl;
list.GetHead(GL);
list.GetTail(GL);
GLnode *T;
cout<<"复制广义表"<<endl;
list.Copy_GList(GL,T);
cout<<"遍历复制后的广义表T"<<endl;
list.Traverse_GList(T);
cout<<endl;
string F;
cout<<"输入广义表F:";
cin>>F;
GList list1;
GLnode *LG;
list1.Create_GList(LG,F);
if(list.Is_Same(GL,LG))
cout<<"广义表S和F相等"<<endl;
else
cout<<"广义表S和F不相等"<<endl;
cout<<"广义表F的长度为:"<<list1.Length_GList_2(LG)<<endl;
char x,y;
cout<<"输入你要替换的字符: ";
cin>>x;
cout<<endl;
cout<<"输入你要替换成哪个字符:";
cin>>y;
GLnode *k;
list1.Replace_GList(LG,x,y,k);
cout<<"替换后的广义表为:";
list1.Traverse_GList(k);
cout<<endl;
cout<<"连接广义表S与被替换字符后的广义表F的表为:";
list.Concat_Glist(GL,k);
list.Traverse_GList(GL);
cout<<endl;
return 0;
}
下面是输出结果
输入广义表S:((a,b),(c,d))
广义表S的深度为:2
广义表S的长度为:2
广义表S的长度为:2
广义表:((a,b),(c,d))
表头为:(a,b)
广义表:((a,b),(c,d))
表尾为:((c,d))
复制广义表
遍历复制后的广义表T
((a,b),(c,d))
输入广义表F:(f,(g,h),(i,i))
广义表S和F不相等
广义表F的长度为:3
输入你要替换的字符: i
输入你要替换成哪个字符:x
替换后的广义表为:(f,(g,h),(x,x))
连接广义表S与被替换字符后的广义表F的表为:((a,b),(c,d),f,(g,h),(x,x))
Press any key to continue