数据结构--广义表

 

 

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


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值