Code:
#include<string.h>
#include<ctype.h>
#include<malloc.h>
#include<limits.h>
#include<stdio.h>
#include<stdlib.h>
#include<io.h>
#include<math.h>
#include<process.h> //exit()
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
typedef char AtomType; //定义原子类型为字符型
typedef int Status; //Status是函数的类型,其值是函数结果状态代码,如OK等
/* 串的堆分配存储表示*/
typedef struct
{
char *ch; //若是非空串,则按串长分配存储区,否则ch为NULL
int length; //串长度
}HString;
/* 广义表的扩展线性链表存储表示*/
typedef enum{ATOM,LIST}ElemTag; //ATOM==0:原子,LIST==1:子表
typedef struct GLNode
{
ElemTag tag; //公共部分,用于区分原子结点和表结点
union //原子结点和表结点的联合部分
{
AtomType atom; //原子结点的值域,AtomType自定义为字符型
struct GLNode *hp; //表结点的表头指针
}a;
struct GLNode *tp; //相当于线性链表的next,指向下一个元素结点
}*GList,GLNode; //广义表类型GList是一种扩展的线性链表
//1. 创建串
Status StrAssign(HString *T,char *chars)
{
int i,j;
if((*T).ch)
free((*T).ch);
i=strlen(chars);
if(!i)
{
(*T).ch=NULL;
(*T).length=0;
}
else
{ //chars的长度不为0
(*T).ch=(char*)malloc(i*sizeof(char));
if(!(*T).ch) //分配串空间失败
exit(OVERFLOW);
for(j=0;j<i;j++) //拷贝串
(*T).ch[j]=chars[j];
(*T).length=i;
}
return OK;
}
//2. 串拷贝:由串S复制得串T
Status StrCopy(HString *T,HString S)
{
int i;
if((*T).ch)
free((*T).ch);
(*T).ch=(char*)malloc(S.length*sizeof(char));
if(!(*T).ch)
exit(OVERFLOW);
for(i=0;i<S.length;i++)
(*T).ch[i]=S.ch[i];
(*T).length=S.length;
return OK;
}
//3. 判断串是否为空:若S为空串,则返回TRUE,否则返回FALSE
Status StrEmpty(HString S)
{
if(S.length==0&&S.ch==NULL)
return TRUE;
else
return FALSE;
}
//4. 比较串长:若S>T,则返回值>0;若S=T,则返回值=0;若S<T,则返回值<0
int StrCompare(HString S,HString T)
{
int i;
for(i=0;i<S.length&&i<T.length;++i)
if(S.ch[i]!=T.ch[i])
return S.ch[i]-T.ch[i];
return S.length-T.length;
}
//5. 取串长:返回S的元素个数,称为串的长度
int StrLength(HString S)
{
return S.length;
}
//6. 清空串:将S清为空串
Status ClearString(HString *S)
{
if((*S).ch)
{
free((*S).ch);
(*S).ch=NULL;
}
(*S).length=0;
return OK;
}
//7. 取子串:用Sub返回串S的第pos个字符起长度为len的子串
Status SubString(HString *Sub, HString S,int pos,int len)
{ //其中,1≤pos≤StrLength(S)且0≤len≤StrLength(S)-pos+1
int i;
if(pos<1||pos>S.length||len<0||len>S.length-pos+1)
return ERROR;
if((*Sub).ch)
free((*Sub).ch); //释放旧空间
if(!len) //空子串
{
(*Sub).ch=NULL;
(*Sub).length=0;
}
else
{ //完整子串
(*Sub).ch=(char*)malloc(len*sizeof(char));
if(!(*Sub).ch)
exit(OVERFLOW);
for(i=0;i<=len-1;i++)
(*Sub).ch[i]=S.ch[pos-1+i];
(*Sub).length=len;
}
return OK;
}
//8. 初始化串:初始化(产生空串)字符串T
void InitString(HString *T)
{
(*T).length=0;
(*T).ch=NULL;
}
//9. 分割串:将非空串str分割成两部分:hstr为第一个','之前的子串,str为之后的子串
Status sever(HString *str,HString *hstr)
{
int n,i=1,k=0; //k记尚未配对的左括号个数
HString ch,c1,c2,c3;
InitString(&ch); //初始化HString类型的变量
InitString(&c1);
InitString(&c2);
InitString(&c3);
StrAssign(&c1,","); //调用创建串函数
StrAssign(&c2,"(");
StrAssign(&c3,")");
n=StrLength(*str); //调用取串长函数
do
{
SubString(&ch,*str,i,1); //取子串
if(!StrCompare(ch,c2)) //调用比较串长函数
++k;
else if(!StrCompare(ch,c3)) //调用比较串长函数
--k;
++i;
}while(i<=n&&StrCompare(ch,c1)||k!=0); //调用比较串长函数
if(i<=n)
{
StrCopy(&ch,*str); //调用串拷贝函数
SubString(hstr,ch,1,i-2); //取子串
SubString(str,ch,i,n-i+1); //取子串
}
else
{
StrCopy(hstr,*str); //调用串拷贝函数
ClearString(str); //清空串str
}
return OK;
}
//10. 创建空的广义表L
Status InitGList(GList *L)
{
*L=NULL;
return OK;
}
//11. 由串S创建广义表L:初始条件为S是广义表的书写形式串
Status CreateGList(GList *L,HString S)
{
HString emp,sub,hsub;
GList p;
InitString(&emp); //初始化HString类型的变量
InitString(&sub);
InitString(&hsub);
StrAssign(&emp,"()"); //调用创建串函数,设emp="()"
*L=(GList)malloc(sizeof(GLNode));
if(!*L) //建表结点不成功
exit(OVERFLOW);
if(!StrCompare(S,emp)) //调用比较串长函数判断若S与emp的串长不相等, 则创建空表
{
(*L)->tag=LIST;
(*L)->a.hp=NULL;
(*L)->tp=NULL;
}
else if(StrLength(S)==1) //若S的串长为1,则创建单原子广义表
{
(*L)->tag=ATOM;
(*L)->a.atom=S.ch[0];
(*L)->tp=NULL;
}
else //创建一般表
{
(*L)->tag=LIST;
(*L)->tp=NULL;
SubString(&sub,S,2,StrLength(S)-2); //脱外层括号
sever(&sub,&hsub); //从sub中分离出表头串hsub
CreateGList(&(*L)->a.hp,hsub); //递归创建广义表L
p=(*L)->a.hp;
while(!StrEmpty(sub)) //调用StrEmpty函数判断表尾是否为空。若否,则重复建n个子表
{
sever(&sub,&hsub); //从sub中分离出表头串hsub
CreateGList(&p->tp,hsub);
p=p->tp;
}
}
return OK;
}
//12. 销毁广义表L
void DestroyGList(GList *L)
{
GList ph,pt;
if(*L) //L不为空表
{ //由ph和pt接替L的两个指针
if((*L)->tag) //是子表
ph=(*L)->a.hp;
else //是原子
ph=NULL;
pt=(*L)->tp;
free(*L); //释放L所指结点
*L=NULL; //令L为空
DestroyGList(&ph); //递归销毁表ph
DestroyGList(&pt); //递归销毁表pt
}
}
//13. 广义表拷贝:由广义表L复制得到广义表T
Status CopyGList(GList *T,GList L)
{
if(!L) //L空
{
*T=NULL;
return OK;
}
*T=(GList)malloc(sizeof(GLNode));
if(!*T)
exit(OVERFLOW);
(*T)->tag=L->tag; //复制枚举变量
if(L->tag==ATOM) //复制共用体部分
(*T)->a.atom=L->a.atom; //复制单原子
else
CopyGList(&(*T)->a.hp,L->a.hp); //函数递归的调用,复制子表
if(L->tp==NULL) //到表尾
(*T)->tp=L->tp;
else
CopyGList(&(*T)->tp,L->tp); //复制子表
return OK;
}
//14. 求广义表L的长度,即元素个数
int GListLength(GList L)
{
int len=0;
GList p;
if(L->tag==LIST&&!L->a.hp) //空表
return 0; //空表返回0
else if(L->tag==ATOM) //单原子表
return 1;
else //一般表
{
p=L->a.hp;
do
{
len++;
p=p->tp;
}while(p);
return len;
}
}
//15. 求广义表L的深度
int GListDepth(GList L)
{
int max,dep;
GList pp;
if(L==NULL||L->tag==LIST&&!L->a.hp)
return 1; //空表深度为1
else if(L->tag==ATOM)
return 0; //单原子表深度为0
else //求一般表的深度
for(max=0,pp=L->a.hp;pp;pp=pp->tp)
{
dep=GListDepth(pp); //递归求以pp为头指针的子表深度
if(dep>max)
max=dep;
}
return max+1; //非空表的深度是各元素的深度的最大值加1
}
//16. 取广义表L的头
GList GetHead(GList L)
{
GList h;
InitGList(&h); // 创建空广义表h
if ( !L || L->tag==LIST && !L->a.hp) // 若L为空表
{
printf ( "\n空表无表头!"); // 输出提示
exit ( 0); // 若表空, 则退出
}
h=(GList)malloc(sizeof(GLNode)); // 为广义表h动态分配内存空间
if ( !h) // 分配空间失败, 退出
exit ( OVERFLOW);
h->tag=L->a.hp->tag; // 取表头
h->tp=NULL;
if ( h->tag==ATOM) // 表头为单原子
h->a.atom=L->a.hp->a.atom;
else // 表头为子表
CopyGList(&h->a.hp,L->a.hp->a.hp);
return h; // 返回表头
}
//17. 取广义表L的尾
GList GetTail(GList L)
{
GList T; // 声明广义表类型变量T
if ( !L) // 若L为空表
{
printf ( "\n空表无表尾!"); // 输出提示
exit ( 0); // 退出
}
T=(GList)malloc(sizeof(GLNode)); // 为广义表T动态分配内存空间
if ( !T) // 分配空间失败, 退出
exit ( OVERFLOW);
T->tag=LIST; // 表尾一定是子表, 省去判断
T->tp=NULL;
CopyGList(&T->a.hp,L->a.hp->tp); // 调用复制广义表函数将表尾赋值给T
return T; // 返回表尾
}
//18. 利用递归算法遍历广义表L
void Traverse_GL(GList L,void(*v)(AtomType))
{
GList hp;
if(L) //L不空
{
if(L->tag==ATOM) //L为单原子
{
v(L->a.atom);
hp=NULL;
}
else //L为子表
hp=L->a.hp;
Traverse_GL(hp,v); //递归调用
Traverse_GL(L->tp,v);
}
}
//19. 访问函数,将作为Traverse_GL函数的实参
void visit(AtomType e)
{
printf("%c ", e);
}
//20. 主函数
void main( )
{
char p[80];
int i;
GList l,m;
HString t;
InitString(&t); // 初始化HString类型的变量
InitGList(&l); // 创建空广义表
InitGList(&m);
do
{
printf ( "\n***************************************\n");
printf ( "\t请输入你选择的操作:\n");
printf ( "\t1、 创建广义表L\n");
printf ( "\t2、 求广义表L的长度\n");
printf ( "\t3、 求广义表L的深度\n");
printf ( "\t4、 利用递归算法遍历广义表L\n");
printf ( "\t5、 复制广义表L至广义表M\n");
printf ( "\t6、 求广义表M的长度\n");
printf ( "\t7、 求广义表M的深度\n");
printf ( "\t8、 利用非递归算法遍历广义表M\n");
printf ( "\t9、 求广义表L的表头,并遍历\n");
printf ( "\t10、求广义表L的表尾,并遍历\n");
printf ( "\t0、 退出\n");
printf ( "***************************************\n");
do
{
printf ( "输入(0-10):");
scanf ( "%d",&i); getchar ( );
}while ( i<0||i>10);
switch(i){
case 1:
printf("请输入广义表L【如(a,(b),b))】:");
gets(p);
StrAssign(&t,p);
printf("广义表L为:%s\n",t);
CreateGList(&l,t); // 由t创建广义表l
break;
case 2:
printf ( "广义表L的长度=%d\n",GListLength(l)); // 调用取广义表长度函数
break;
case 3:
printf ( "广义表L的深度=%d \n",GListDepth(l)); // 调用取广义表深度函数
break;
case 4:
printf ( "利用递归算法遍历广义表L:\n");
Traverse_GL(l,visit); // 调用访问函数,处理l的每个元素
printf ( "\n");
break;
case 5:
CopyGList(&m,l);
printf ( "已复制广义表L至广义表M,广义表M为:%s\n",t);
break;
case 6:
printf ( "广义表M的长度=%d\n",GListLength(m)); // 调用取广义表长度函数
break;
case 7:
printf ( "广义表M的深度=%d\n",GListDepth(m)); // 调用取广义表深度函数
break;
case 8:
printf ( "利用非递归算法遍历广义表M:\n");
Traverse_GL(m,visit); // 调用访问函数,处理m的每个元素
printf ( "\n");
break;
case 9:
DestroyGList(&m); // 销毁广义表m
m=GetHead(l); // 取广义表l的头
printf ( "求广义表L的表头,并遍历:\n");
Traverse_GL(m,visit); // 遍历广义表m
printf ( "\n");
break;
case 10:
DestroyGList(&m); // 销毁广义表m
m=GetTail(l); // 取广义表l的尾
printf ( "m求广义表L的表尾,并遍历:\n");
Traverse_GL(m,visit); // 遍历广义表m
printf ( "\n");
}
}while ( i);
printf ( "\n");
DestroyGList(&m); // 销毁广义表m
system("PAUSE"); // 屏幕暂停
}