数据结构C语言版广义表的头尾链表存储表示.docx
《数据结构C语言版广义表的头尾链表存储表示.docx》由会员分享,可在线阅读,更多相关《数据结构C语言版广义表的头尾链表存储表示.docx(17页珍藏版)》请在冰豆网上搜索。
数据结构C语言版广义表的头尾链表存储表示
数据结构C语言版广义表的头尾链表存储表示
P109
编译环境:
Dev-C++4.9.9.2
日期:
2011年2月13日
*/
#include
#include
#include
#include
typedefcharAtomType;//定义原子类型为字符型
typedefenum{
ATOM,//ATOM==0:
原子
LIST//LIST==1:
子表
}ElemTag;
//广义表的头尾链表存储表示
typedefstructGLNode
{
ElemTagtag;//公共部分,用于区分原子结点和表结点
union//原子结点和表结点的联合部分
{
AtomTypeatom;//atom是原子结点的值域,AtomType由用户定义
struct
{
structGLNode*hp,*tp;
}ptr;//ptr是表结点的指针域,prt.hp和ptr.tp分别指向表头和表尾
}a;
}*GList,GLNode;//广义表类型
//创建空的广义表L
intInitGList(GList*L)
{
*L=NULL;
return1;
}
//销毁广义表L
voidDestroyGList(GList*L)
{
GListq1,q2;
if(*L)
{
if((*L)->tag==ATOM)
{
free(*L);//删除原子结点
*L=NULL;
}
else//是表结点,则应该删除表头和表尾结点
{
q1=(*L)->a.ptr.hp;
q2=(*L)->a.ptr.tp;
free(*L);
*L=NULL;
//递归删除表头和表尾结点
DestroyGList(&q1);
DestroyGList(&q2);
}
}
}
//算法5.6P115
//采用头尾链表存储结构,由广义表L复制得到广义表T。
intCopyGList(GList*T,GListL)
{
if(!
L)//为空,复制空表
*T=NULL;
else
{
*T=(GList)malloc(sizeof(GLNode));//建表结点
if(!
*T)
exit(0);
(*T)->tag=L->tag;
if(L->tag==ATOM)
(*T)->a.atom=L->a.atom;//复制单原子
else//是表结点,则依次复制表头和表尾
{
//复制广义表L->ptr.hp的一个副本T->ptr.hp
CopyGList(&((*T)->a.ptr.hp),L->a.ptr.hp);
//复制广义表L->ptr.tp的一个副本T->ptr.tp
CopyGList(&((*T)->a.ptr.tp),L->a.ptr.tp);
}
}
return1;
}
//返回广义表的长度,即元素个数
intGListLength(GListL)
{
intlen=0;
if(!
L)
return0;
if(L->tag==ATOM)
return1;
while(L)
{
L=L->a.ptr.tp;//根据表尾来判断
len++;
}
returnlen;
}
//算法5.5P114
//采用头尾链表存储结构,求广义表L的深度。
intGListDepth(GListL)
{
intmax,dep;
GListpp;
if(!
L)
return1;//空表深度为1
if(L->tag==ATOM)
return0;//原子深度为0
for(max=0,pp=L;pp;pp=pp->a.ptr.tp)
{
//递归求以pp->a.ptr.hp为头指针的子表深度
dep=GListDepth(pp->a.ptr.hp);
if(dep>max)
max=dep;
}
returnmax+1;//非空表的深度是各元素的深度的最大值加1
}
//判定广义表是否为空
intGListEmpty(GListL)
{
if(!
L)
return1;
else
return0;
}
//取广义表L的头
GListGetHead(GListL)
{
GListh,p;
if(!
L)
{
printf("空表无表头!
\n");
exit(0);
}
p=L->a.ptr.tp;//保存表尾
L->a.ptr.tp=NULL;
CopyGList(&h,L);
L->a.ptr.tp=p;//归还表尾
returnh;
}
//取广义表L的尾
GListGetTail(GListL)
{
GListt;
if(!
L)
{
printf("空表无表尾!
\n");
exit(0);
}
CopyGList(&t,L->a.ptr.tp);
returnt;
}
//插入元素e作为广义表L的第一元素(表头,也可能是子表)
intInsertFirst_GL(GList*L,GListe)
{
GListp=(GList)malloc(sizeof(GLNode));
if(!
p)
exit(0);
p->tag=LIST;
p->a.ptr.hp=e;
p->a.ptr.tp=*L;
*L=p;
return1;
}
//删除广义表L的第一元素,并用e返回其值
intDeleteFirst_GL(GList*L,GList*e)
{
GListp;
*e=(*L)->a.ptr.hp;//用*e返回表头
p=*L;
*L=(*L)->a.ptr.tp;//将表尾当成表L
free(p);//删除表头
return1;
}
//利用递归算法遍历广义表L
voidTraverse_GL(GListL,void(*v)(AtomType))
{
if(L)//L不空
if(L->tag==ATOM)//L为单原子
v(L->a.atom);
else//L为广义表
{
Traverse_GL(L->a.ptr.hp,v);
Traverse_GL(L->a.ptr.tp,v);
}
}
//串的定长顺序存储表示
#defineMAXSTRLEN40//用户可在255以内定义最大串长(1个字节)
typedefcharSString[MAXSTRLEN+1];//0号单元存放串的当前长度
//生成一个其值等于chars的串T
intStrAssign(SStringT,char*chars)
{
inti;
if(strlen(chars)>MAXSTRLEN)
return0;
else
{
T[0]=strlen(chars);//记录长度
//一个一个的拷贝,字符串结束符也拷贝了
for(i=1;i<=T[0];i++)
T[i]=*(chars+i-1);
return1;
}
}
//由串S复制得串T
intStrCopy(SStringT,SStringS)
{
inti;
//一个一个的拷贝
for(i=0;i<=S[0];i++)
T[i]=S[i];
return1;
}
//若S为空串,则返回1,否则返回0
intStrEmpty(SStringS)
{
if(S[0]==0)
return1;
else
return0;
}
//若S>T,则返回值>0;若S=T,则返回值=0;若SintStrCompare(SStringS,SStringT)
{
inti;
for(i=1;i<=S[0]&&i<=T[0];++i)
if(S[i]!
=T[i])
returnS[i]-T[i];
returnS[0]-T[0];
}
//返回串的元素个数
intStrLength(SStringS)
{
returnS[0];
}
//将S清为空串
intClearString(SStringS)
{
S[0]=0;//令串长为零
return1;
}
//算法4.3P74
//用Sub返回串S的第pos个字符起长度为len的子串。
intSubString(SStringSub,SStringS,intpos,intlen)
{
inti;
if(pos<1||pos>S[0]||len<0||len>S[0]-pos+1)
return0;
for(i=1;i<=len;i++)
Sub[i]=S[pos+i-1];
Sub[0]=len;
return1;
}
//算法5.8P117
//将非空串str分割成两部分:
hsub为第一个','之前的子串,str为之后的子串
voidsever(SStringstr,SStringhstr)
{
intn,i,
k;//k记尚未配对的左括号个数
SStringch,c1,c2,c3;
n=StrLength(str);
StrAssign(c1,",");
StrAssign(c2,"(");
StrAssign(c3,")");
SubString(ch,str,1,1);
//搜索最外层的第一个逗号
for(i=1,k=0;i<=n&&StrCompare(ch,c1)||k!
=0;++i)
{
SubString(ch,str,i,1);
if(!
StrCompare(ch,c2))
++k;
elseif(!
StrCompare(ch,c3))
--k;
}
if(i<=n)
{
SubString(hstr,str,1,i-2);
SubString(str,str,i,n-i+1);
}
else
{
StrCopy(hstr,str);
ClearString(str);
}
}
//算法5.7P117
//采用头尾链表存储结构,由广义表的书写形式串S(即类似(,()))创建
//广义表L。
设emp="()"
intCreateGList(GList*L,SStringS)
{
SStringsub,hsub,emp;
GListp,q;
StrAssign(emp,"()");
if(!
StrCompare(S,emp))
*L=NULL;//创建空表
else
{
*L=(GList)malloc(sizeof(GLNode));
if(!
*L)//建表结点
exit(0);
if(StrLength(S)==1)//S为单原子
{
(*L)->tag=ATOM;
(*L)->a.atom=S[1];//创建单原子广义表
}
else
{
(*L)->tag=LIST;
p=*L;
SubString(sub,S,2,StrLength(S)-2);//脱外层括号
do
{//重复建n个子表
sever(sub,hsub);//从sub中分离出表头串hsub
CreateGList(&p->a.ptr.hp,hsub);
q=p;
if(!
StrEmpty(sub))//表尾不空
{
p=(GLNode*)malloc(sizeof(GLNode));
if(!
p)
exit(0);
p->tag=LIST;
q->a.ptr.tp=p;
}
}while(!
StrEmpty(sub));
q->a.ptr.tp=NULL;
}
}
return1;
}
//打印原子
voidvisit(AtomTypee)
{
printf("%c",e);
}
intmain()
{
//广义表的表示形式是,空表:
(),单原子:
a,表:
(a,(b),c,(d,(e)))
charp[80]={"(a,(b),c,(d,(e)))"};
SStringt;
GListL,m;
InitGList(&L);
InitGList(&m);
printf("空广义表L的深度=%d\nL是否空?
%d(1:
是0:
否)\n\n",
GListDepth(L),GListEmpty(L));
StrAssign(t,p);
//创建广义表
CreateGList(&L,t);
printf("\n广义表L的长度=%d\n",GListLength(L));
printf("广义表L的深度=%d\nL是否空?
%d(1:
是0:
否)\n",
GListDepth(L),GListEmpty(L));
printf("遍历广义表L:
\n");
Traverse_GL(L,visit);
printf("\n\n复制广义表m=L\n");
CopyGList(&m,L);
printf("广义表m的长度=%d\n",GListLength(m));
printf("广义表m的深度=%d\n",GListDepth(m));
printf("遍历广义表m:
\n");
Traverse_GL(m,visit);
//重复用的时候记得销毁,相当于初始化
DestroyGList(&m);
m=GetHead(L);
printf("\n\nm是L的表头,遍历广义表m:
\n");
Traverse_GL(m,visit);
//重复用的时候记得销毁,相当于初始化
DestroyGList(&m);
m=GetTail(L);
printf("\n\nm是L的表尾,遍历广义表m:
\n");
Traverse_GL(m,visit);
//插入到表头
InsertFirst_GL(&m,L);
printf("\n\n插入L为m的表头,遍历广义表m:
\n");
Traverse_GL(m,visit);
printf("\n\n删除m的表头,遍历广义表m:
\n");
DestroyGList(&L);
DeleteFirst_GL(&m,&L);
Traverse_GL(m,visit);
printf("\n");
DestroyGList(&m);
system("pause");
return0;
}
/*
输出效果:
空广义表L的深度=1
L是否空?
1(1:
是0:
否)
广义表L的长度=4
广义表L的深度=3
L是否空?
0(1:
是0:
否)
遍历广义表L:
abcde
复制广义表m=L
广义表m的长度=4
广义表m的深度=3
遍历广义表m:
abcde
m是L的表头,遍历广义表m:
a
m是L的表尾,遍历广义表m:
bcde
插入L为m的表头,遍历广义表m:
abcdebcde
删除m的表头,遍历广义表m:
bcde
请按任意键继续...
*/