您的位置:首页 > 理论基础 > 数据结构算法

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

2017-09-20 21:32 323 查看
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(!head) return;
           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(!L) return
(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(!L) return
(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(!*dest) return
(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;
}
 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: