33. 数据结构笔记之三十三广义表实现二

33. 数据结构笔记之三十三广义表实现二

希望是附丽于存在的,有存在,便有希望,有希望,便是光明。--鲁迅

我们继续来看下广义表的其他代码实现。代码均来自网络,均亲测可行。

1.  广义表实现二

1.1       main

创建两个链表的指针head和L。

输入一个字符串,调用GLCreate函数创建广义表。显示,获取头表,尾表,输出长度,深度,原子个数,复制列表,Merge列表,遍历,比较广义表操作。

代码如下:

int main()

{

           chars[MAXSIZE],a[MAXSIZE];

           GListhead;

           GListL;

           printf("pleaseinput a string:");

           scanf("%s",s);

           head= GLCreate(s);

           DisplayList(head);

           printf("\n");

           printf("TheHead is:");

           DisplayList(GetHead(head));

           printf("\n");

           printf("TheTail is: ");

           DisplayList(GetTail(head));

           printf("\n");

           printf("TheLength is %d\n",Length(head));

           printf("TheDepth is %d\n",Depth(head));

           printf("TheAtom number is %d\n",CountAtom(head));

           printf("Copythe List:\n");

           CopyList(&L,head);

           DisplayList(L);

           printf("\n");

           printf("Mergethe List\n");

           Merge(&L,head);

           DisplayList(L);

           printf("\n");

           printf("PreOrder:");

           PreOrder(head);

           printf("\n");

           printf("inputa string:");

           scanf("%s",a);

           L =GLCreate(a);

           DisplayList(L);

           printf("Eqaul ");

           DisplayList(head);

           printf(":");

           if(Equal(L,head)) printf("yes!\n");

           elseprintf("no!\n");

           return0;

}

1.2      定义结构体

定义结构体,同实现一

typedefstructGLNode

{

           ElemTagtag;

           union

           {

                     AtomType  atom;

                     structGLNode*hp;

           }atom_hp;

           structGLNode*tp;

}GLNode,*GList;

 

 

1.3       GLCreate

根据输入的字符串,建立广义表,成功则返回建立的广义表的表头,否则,返回NULL。

具体过程是这个样子的,先创建变量p,q,r,head。 然后先获取输入字符串的长度,对比字符串是否为“()”,以及字符串长度是否为0,如果满足其中之一,直接设置head=NULL,并返回head。

如果字符串长度为1,那么创建一个原子节点,并返回。

如果其他情况,创建一个head节点,设置tag为1,复制给p。然后将除去()之外的字符串赋值给substr临时变量。

 然后取出substr的表头,让p指向这个表头,然后赋值给q. 接着计算剩余字符串的长度,如果大于0,则创建一个节点p,让q指向p. 根据len 是否大于零,继续取出表头进行循环。最后返回head.

PS:函数更多的是功能的实现,所以输入需要当前使用的朋友自己把关。原子节点也是一个字符。

 

 

 

1.4       Disastr

分离出广义表中表头部分,分离后剩下的字符串,不包括逗号

具体描述:

输入两个字符串的指针s,hstr。如果*s不为NULL且不是’,’ 或者K不为0,则进入第一个循环,判断是否*s为’(‘,如果是则K++. 如果是‘)’,则K- -。(K是括号计数器)

如果*s 为‘,’并且k不为0 或者 *s不为’,’ ,将*s赋值给hstr.

然后将剩余的留给rstr并通过s指针返回。

void Disastr(char *s,char *hstr)

{

           inti,j,k,r;

           charrstr[MAXSIZE];

 

           i=j=k=0;

           while(s[i]&& (s[i] != ','|| k))

           {

                     if (s[i]== '(') {  k++ ; }        // k 作为括号计数器       

                     elseif (s[i]== ')') {k--;}

                     if (s[i]!= ',' || s[i]== ',' && k)

                     {

                                hstr[j]= s[i];

                                i++;

                                j++;

                     }

           }

           hstr[j]= '/0';

           if (s[i]== ',') {i++;}

           r=0;

           while(s[i])                 // 处理剩余的表尾部分

           {

                     rstr[r]= s[i];

                     r++;

                     i++;

           }

           rstr[r]= '/0';

           strcpy(s,rstr);

}

1.5       GetHead

取出广义表的表头部分,成功则返回广义表的表头,否则,返回空或退出。

具体描述:

如果为空,则返回NULL,如果tag为0,则退出,否则返回指针。

1.6       GetTail

取出广义表的表尾部分,成功返回广义表的表尾部分,否则,返回空或者退出。

 

1.7       DisplayList

打印广义表。

1.8       Length

求出广义表的长度,返回广义表的长度。

 

1.9       Depth

求得广义表的深度,求广义表的深度。

1.10   CountAtom

统计原子结点的个数。

1.11   CopyList

完成广义表的复制,将res复制到dest中,成功返回1,否则,返回0

1.12   Merge

合并广义表,如果p为空,则申请空间,将q复制到p中。

例如:((a,b),c) 和(a,b)合并之后为:((a,b),c,a,b)

算法描述:先找到第一个广义表的最后一个结点,将其链到第二个广义表的首元素即可

1.13   PreOrder

类似二叉树的先序遍历遍历广义表L

例如(a,(b,(c),d))结果为:a,b,c,d

L若为原子结点,显示该数据,递归调用遍历后续元素。

L是子表结点,递归调用遍历该子表,遍历后续元素。

1.14   Equal

判断两个广义表是否相等,相等,返回1,否则,返回0

相等的定义:两个广义表具有相同的存储结构,对应的原子结点的数据域也相等

1.15  源码

#include<stdio.h>

#include<string.h>

#include<stdlib.h>

#defineAtomTypechar

#defineMAXSIZE  1024

#defineElemTagint

#defineOK       1

#defineERROR    0

 

typedefstructGLNode

{

           ElemTagtag;

           union

           {

                     AtomType  atom;

                     structGLNode*hp;

           }atom_hp;

           structGLNode*tp;

}GLNode,*GList;

 

//功能:分离出广义表中表头部分

//返回:分离后剩下的字符串,不包括逗号

void Disastr(char *s,char *hstr)

{

           inti,j,k,r;

           charrstr[MAXSIZE];

 

           i=j=k=0;

           while(s[i]&& (s[i] != ','|| k))

           {

                     if (s[i]== '(') {  k++ ; }        // k 作为括号计数器       

                     elseif (s[i]== ')') {k--;}

                     if (s[i]!= ',' || s[i]== ',' && k)

                     {

                                hstr[j]= s[i];

                                i++;

                                j++;

                     }

           }

           hstr[j]= '\0';

           if (s[i]== ',') {i++;}

           r=0;

           while(s[i])                 // 处理剩余的表尾部分

           {

                     rstr[r]= s[i];

                     r++;

                     i++;

           }

           rstr[r]= '\0';

           strcpy(s,rstr);

}

//功能:根据输入的字符串,建立广义表

//返回:成功则返回建立的广义表的表头,否则,返回NULL

GLNode * GLCreate(char *s)

{

           GLNode*p,*q,*r,*head;

           charsubstr[MAXSIZE],hstr[MAXSIZE];//rstr[MAXSIZE];

           intlen;

           len= strlen(s);

           if (!strcmp(s,"()")|| !len)  { head = NULL;}     // (1) 空表情况

           elseif(len == 1)                                     // (2) 原子情况

           {

                     head= (GLNode *)malloc(sizeof(GLNode));       // 建立一个新结点

                     if(!head)  returnNULL;    

                     head->tag= 0;                                 //构造原子结点

                     head->atom_hp.atom= *s;

                     head->tp= NULL;

           }

           else                                               // (3) 子表情况

           {

                     head= (GLNode *)malloc(sizeof(GLNode));

                     if(!head) returnNULL;

                     head->tag= 1;

                     p= head;

                     s++;

                     strncpy(substr,s,len-2);                         //剥去外层的()

                     substr[len-2]= '\0';

                     do

                     {

                                Disastr(substr,hstr);                        //分离出表头

                                r= GLCreate(hstr);

                                p->atom_hp.hp= r;                           //尾插法建表

                                q=p;

                                len= strlen(substr);

                                if(len > 0)

                                {

                                          p= (GLNode*)malloc(sizeof(GLNode));

                                          if(!p) returnNULL;

                                          p->tag= 1;

                                          q->tp=p;

                                }

                     }while(len > 0);

                     q->tp=NULL;

           }

           returnhead;

}

void DisplayList(GListhead)

{

           GLNode*p,*q;

 

           if(!headreturn;

           if (head->tag==0)

           {

                     printf("%c",head->atom_hp.atom);

                     return;

           }

           printf("(");

           if (head)

           {

                     do

                     {

                                p= head->atom_hp.hp;

                                q= head->tp;

                                while(q && p && p->tag == 0)                //  同一层的原子结点

                                {

                                          printf("%c,",p->atom_hp.atom);

                                          p= q->atom_hp.hp;

                                          q= q->tp;

                                }

                                if(p && !p->tag)                           //最后一个原子结点

                                {

                                          printf("%c",p->atom_hp.atom);

                                          break;

                                }

                                else                                        //子表情况

                                {

                                          if(!p) printf("()");

                                          elseDisplayList(p);

                                          if(q)  printf(",");

                                          head =q;

                                }

                     }while (head);

                     printf(")");

           }

}

//功能:取出广义表的表头部分

//返回:成功则返回广义表的表头,否则,返回空或退出

GList GetHead(GListL)

{

           if(!Lreturn (NULL);                    // 空表无表头

           if (L->tag== 0)  exit(0);                 // 原子结点不是表

           elsereturn (L->atom_hp.hp);

}

//功能:取出广义表的表尾部分

//返回:成功返回广义表的表尾部分,否则,返回空或者退出

GList GetTail(GListL)

{

           if(!L) return (NULL);

           if (L->tag== 0) exit(0);

           elsereturn (L->tp);

}

//功能:求出广义表的长度

//返回值:广义表的长度

int Length(GListL)

{

           intk=0;

           GLNode*s;

           if(!L) return0;                    //空表的长度为零

           if (L->tag== 0) exit(0);            //原子不是表

           s=L;

           while(s)                             //统计表的最上层的长度

           {

                     k++;

                     s=s->tp;

           }

           returnk;

}

 

//功能:求得广义表的深度

//输入:需求深度的广义表的指针

int Depth(GListL)

{

           intd,max;

           GLNode*s;

           if(!Lreturn (1);            // 空表的深度为 1

           if (L->tag==0)  return 0;       // 原子的深度为 0

           s=L;

           max=0;

           while(s)                        //递归求每个子表深度的最大值

           {

                     d= Depth(s->atom_hp.hp);

                     if(d > max) max = d;

                     s= s->tp;

           }

           return(max+1);                  //表的深度为子表深度加一

}

 

//功能:统计原子结点的个数

//输入:需统计的广义表指针

int CountAtom(GListL)

{

           intn1,n2;

           if(!L) return0;                   //空表无原子结点

           if (L->tag==0)return1;            // 原子结点

           n1 =CountAtom(L->atom_hp.hp);     

           n2 =CountAtom(L->tp);

           return(n1+n2);

}

//功能:完成广义表的复制,res复制到dest

//返回:成功返回1,否则,返回0

bool CopyList(GList *dest,GListres)

{

           if(!res) {*dest =NULL;return (OK);}

           *dest =(GLNode*)malloc(sizeof(GLNode));

           if(!*destreturn (ERROR);

           (*dest)->tag= res->tag;

           if (res->tag==0)  (*dest)->atom_hp.atom= res->atom_hp.atom;

           else

           {

                     CopyList(&(*dest)->atom_hp.hp,res->atom_hp.hp);

                     CopyList(&(*dest)->tp,res->tp);

           }

           return (OK);

}

//功能:合并广义表,如果p为空,则申请空间,将q复制到p

//例如:((a,b),c)(a,b)合并之后为:((a,b),c,a,b)

//算法描述:先找到第一个广义表的最后一个结点,将其链到第二个广义表的首元素即可

void Merge(GList *p,GLNode *q)

{

           GLNode*r;

           if(!q) return;       //  如果复制的是个空表,返回

           if(!p)               // p为空,申请空间

           {

                     *p =(GLNode*)malloc(sizeof(GLNode));

                     if(!(*p)) return ;

                     (*p)->tag= 1;

           }

           else

           {

                     if((*p)->tag)        

                     {

                                r=*p;

                                while(r->tp)r=r->tp;             //找到最后一个子表的表尾指针

                                if (q->tag)r->tp = q;        // 修改表尾指针

                     }

           }

}

//功能:类似二叉树的先序遍历遍历广义表L

//eg:例如(a,(b,(c),d))结果为:a,b,c,d

//算法描述:

//L若为原子结点,显示该数据,递归调用遍历后续元素,也即:write(L->atom_hp.atom);PreOrder(L->tp);

//L是子表结点,递归调用遍历该子表,遍历后续元素,也即:PreOrder(L->atom_hp.tp);PreOrder(L->tp);

void PreOrder(GListL)

{

           if (L)

           {

                     if (L->tag==0)printf("%c ",L->atom_hp.atom);   // 打印原子结点

                     else  PreOrder(L->atom_hp.hp);                  // 往下遍历,类似二叉树中的左子树

                     if (L->tp)PreOrder(L->tp);                     // 往右遍历,类似二叉树中的右子树

           }

}

// 判断两个广义表是否相等,相等,返回1,否则,返回0

// 相等的定义:两个广义表具有相同的存储结构,对应的原子结点的数据域也相等

//算法描述:

// 形式:条件

//Equal(p,q) = Equal(p->tp,q->tp) ; p->tag= 0 && q->tag = 0 && p->atom_hp.atom = q->atom_hp.atom

//Equal(p,q) =Equal(p->atom_hp.hp,q->atom_hp.hp) && Equal(p->tp,q->tp) ;p->tag = 1 && q->tag = 1

//Equal(p,q) = false     ; p->tag = 0 && q->tag = 0p->atom_hp.atom != q->atom_hp.atom 或者p->tag *p->tag + q->tag*q->tag =1

//Equal(p,q) = false      ; p q 其中之一为NULL

bool Equal(GListp,GListq)

{

           boolflags = true;

           if(!p && q)flags = false;

           if (p&& !q) flags = false;

           if (p&& q)

           {

                     if (p->tag== 0 && q->tag == 0 )

                     {

                                if (p->atom_hp.atom!= q->atom_hp.atom)

                                          flags= false;

                     }

                     elseif (p->tag== 1 && q->tag == 1)

                     {

                                flags= Equal(p->atom_hp.hp,q->atom_hp.hp);

                     }

                     elseflags = false;

                     if(flags) flags = Equal(p->tp,q->tp);

           }

           returnflags;

}

int main()

{

           chars[MAXSIZE],a[MAXSIZE];

           GListhead;

           GListL;

           printf("pleaseinput a string:");

           scanf("%s",s);

           head= GLCreate(s);

           DisplayList(head);

           printf("\n");

           printf("TheHead is:");

           DisplayList(GetHead(head));

           printf("\n");

           printf("TheTail is: ");

           DisplayList(GetTail(head));

           printf("\n");

           printf("TheLength is %d\n",Length(head));

           printf("TheDepth is %d\n",Depth(head));

           printf("TheAtom number is %d\n",CountAtom(head));

           printf("Copythe List:\n");

           CopyList(&L,head);

           DisplayList(L);

           printf("\n");

           printf("Mergethe List\n");

           Merge(&L,head);

           DisplayList(L);

           printf("\n");

           printf("PreOrder:");

           PreOrder(head);

           printf("\n");

           printf("inputa string:");

           scanf("%s",a);

           L =GLCreate(a);

           DisplayList(L);

           printf("Eqaul ");

           DisplayList(head);

           printf(":");

           if(Equal(L,head)) printf("yes!\n");

           elseprintf("no!\n");

           return0;

}

 

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值