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"); // 屏幕暂停 }