广义表实验报告Word格式文档下载.docx
《广义表实验报告Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《广义表实验报告Word格式文档下载.docx(15页珍藏版)》请在冰豆网上搜索。
销毁广义表L
CopyGlist(&
T,L);
由广义表L复制得到广义表T
GListLength(L);
求广义表L的长度,即元素个数
GListDepth(L);
求广义表L的深度
GlistEmpty(L);
判断广义表L是否为空
GetHead(L);
取广义表L的头
GetTail(L)
取广义表L的尾
InsertFirst_GL(&
L,e)
插入元素e作为广义表L的第一元素
DeleteFirst_GL(GList&
L,&
e)
删除广义表L的第一元素,并用e返回其值
Traverse_GL(GListL,void(*v)(AtomType))
遍历广义表L,用函数Visit处理每个元素
}ADTGList
2.存储结构定义
由于广义表中的数据元素可以具有不同的结构(或是原子,或是列表),因此难以用顺序存储结构表示,通常采用链式存储结构,每个数据元素可用一个节点表示。
由于列表中的数据元素可能为原子或列表,由此需要两种结构的结点:
一种是表结点,用以表示列表;
一种是原子结点,用以表示原子。
一个表结点可以由3个域组成:
标志域,指示表头的指针域和指示表尾的指针域;
而原子结点只需两个域:
标志域和值域。
其形式定义说明如下:
-------广义表的扩展线性链表存储表示------
typedefenum{ATOM,LIST}ElemTag;
//ATOM==0:
原子,LIST==1:
子表
typedefstructGLNode{
ElemTagtag;
//公共部分,用于区分原子结点和表结点
union{//原子结点和表结点的联合部分
AtomTypeatom;
//atom是原子结点的值域AtomType由用户定义
struct{structGLNode*hp,*tp;
}ptr;
//ptr是表结点的指针域,ptr.hp和ptr.tp分别指向表头和表尾
};
}*GList;
//广义表类型
voidvisit(GListL){//visit函数
printf("
%c"
L->
atom);
}
voidGetGList(chars[])
{//接收建表元素--书写形式串的函数
inti;
\nInputGListtocreat:
\n"
);
for(i=0;
i<
50;
i++)
{
scanf("
&
s[i]);
if(s[i]=='
\n'
)
break;
}
3.算法设计
intInitGList(GList&
L)//建空广义表
{
L=(GList)malloc(sizeof(structGLNode));
if(!
L)returnERROR;
L->
tag=LIST;
ptr.hp=NULL;
ptr.tp=NULL;
returnOK;
GListCreatGList(GList&
L,char*s){//由书写形式串建广义表
GListq;
charx;
x=*s;
s++;
if(x!
='
){
q=(GList)malloc(sizeof(structGLNode));
if(x=='
('
q->
ptr.hp=CreatGList(L,s);
elseif(x=='
)'
if(*s!
'
q=NULL;
x=*s;
s++;
if(x=='
q=(GList)malloc(sizeof(structGLNode));
ptr.tp=CreatGList(L,s);
}
else{
tag=ATOM;
atom=x;
}
}//if
elseq=NULL;
if(q!
=NULL)
if(x=='
q->
else
L=q;
returnL;
intDestroyGList(GList&
L)//销毁广义表
{
GListph,pt;
if(L)
{
if(L->
tag)
ph=L->
ptr.hp;
ph=NULL;
pt=L->
ptr.tp;
free(L);
L=NULL;
DestroyGList(ph);
DestroyGList(pt);
}
returnOK;
GListCopyGList(GList&
T,GListL)//复制广义表
{
if(!
L)T=NULL;
else{
T=(GList)malloc(sizeof(structGLNode));
T->
tag=L->
tag;
tag==ATOM)
T->
atom=L->
atom;
else
CopyGList(T->
ptr.hp,L->
ptr.hp);
ptr.tp,L->
ptr.tp);
returnT;
intGListLength(GListL)//求广义表长度
inti=0;
GListp;
p=L;
if(p->
tag==LIST&
&
!
p->
ptr.hp)
return0;
elseif(p->
return1;
p=L->
for(i=0;
p;
p=p->
ptr.tp,i++);
returni;
-
intGListDepth(GListL)//求广义表深度
intmax,dep;
GListp;
p=L;
L||p->
ptr.hp==NULL)
return1;
elseif(p->
return0;
else
for(max=0,p=L->
ptr.tp)
dep=GListDepth(p);
if(dep>
max)
max=dep;
returnmax+1;
intGListEmpty(GListL)//判断广义表是否为空
L||L->
return1;
return0;
GListGetHead(GListL)//取广义表表头
GListp,h;
\nEmptyGList-NoGListhead!
returnNULL;
p=(GList)malloc(sizeof(structGLNode));
h=L->
tag=h->
if(p->
ptr.hp->
CopyGList(p->
returnp;
GListGetTail(GListL)//取广义表表尾
L)
\nEmptyGList-NoGListtail!
returnNULL;
p=(GList)malloc(sizeof(structGLNode));
p->
CopyGList(p->
returnp;
intInsertFirst_GL(GListL,GListe)//插入一个元素作为广义表的第一元素
p=L->
L->
ptr.hp=e;
e->
ptr.tp=p;
intDeleteFirst_GL(GList&
L,GList&
e)//删除广义表的第一元素
if(L){
e=L->
L->
ptr.hp=e->
e->
e=L;
voidTraverse_GL(GList&
L,voidvisit(GListL))//遍历广义表
if(L!
=NULL){
if(L->
tag==LIST){
printf("
("
if(!
printf("
"
else
Traverse_GL(L->
ptr.hp,visit);
else
visit(L);
tag==LIST)
)"
ptr.tp!
=NULL){
"
Traverse_GL(L->
ptr.tp,visit);
printf("
\nEmptyGList!
4.测试
voidmain()
{GListL,T,d,f,head,tail;
inta;
chars[50],add[50],*p,*q;
p=s;
q=add;
InitGList(L)&
InitGList(T)){
FailtoinitGList!
return;
do{//操作界面
\n\n请选择功能\n"
------------------------------------\n"
1创建广义表\n"
2销毁广义表\n"
3复制广义表\n"
4求广义表长度\n"
5求广义表深度\n"
6判断广义表是否为空\n"
7取广义表表头\n"
8取广义表表尾\n"
9插入一个元素\n"
10删除一个元素\n"
11遍历广义表\n"
12退出程序\n"
请输入你想进行的操作项的序号:
\n"
scanf("
%d"
a);
switch(a){
case1:
getchar();
GetGList(s);
CreatGList(L,p);
break;
case2:
if(DestroyGList(L))
Succeedtodestroy.\n"
case3:
CopyGList(T,L);
\n原表是:
Traverse_GL(L,visit);
\n复制所得的表是:
Traverse_GL(T,visit);
case4:
表的长度是%d\n"
GListLength(L));
case5:
表的深度是%d\n"
GListDepth(L));
case6:
if(GListEmpty(L))
printf("
EmptyGList!
else
NotEmptyGList!
case7:
表头是:
head=GetHead(L);
Traverse_GL(head,visit);
case8:
表尾是:
tail=GetTail(L);
Traverse_GL(tail,visit);
case9:
输入要插入的元素:
getchar();
GetGList(add);
CreatGList(f,q);
InsertFirst_GL(L,f);
Traverse_GL(L,visit);
case10:
DeleteFirst_GL(L,d);
删除后的广义表是:
case11:
Traverse_GL(L,visit);
case12:
default:
\nInputERROR!
getchar();
}//switch
while
(1);
6.思考与小结
通过本次广义表的设计性实验,加深了我对广义表的存储结构和基本抽象数据类型的实现的理解。
由于广义表的操作涉及不少循环和递归的算法,所以本次实验后,我对递归算法的调用有了进一步的了解。
广义表的存储结构也是挺有意思的,很多情况下它的表头也是一个广义表,表尾也是一个广义表。
这就决定了用递归算法去实现它会是的算法更加的简洁。
同时,它的结构也和二叉树有很大的相似性,所以,广义表的抽象数据类型的实现会对数的结构的学习也有一定的帮助。
本次实验的难点主要是CreatGList函数。
由于广义表是由字符串创建的,所以,会涉及一些串的操作,本次实验尽量避开了串的操作,所以部分函数实现起来困难会增加。
难点就在于要判断什么时候该创建表头,什么时候该创建表尾,以及什么时候结束。
由于设计时用了递归的技巧,所以程序的每一行都要非常注意,失之毫厘差之千里,在设计函数过程中一个个的错误让我体会到程序设计的严谨性。