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;
}