实验二线性表的链式表示和实现.docx
《实验二线性表的链式表示和实现.docx》由会员分享,可在线阅读,更多相关《实验二线性表的链式表示和实现.docx(14页珍藏版)》请在冰豆网上搜索。
实验二线性表的链式表示和实现
学校代码:
10128
学号:
201220905048
《数据结构》实验报告
(
题目:
线性表的链式表示和实现
学生姓名:
孙跃
学院:
理学院
系别:
数学系
专业:
信息与计算科学
班级:
信计12-2
任课教师:
杜雅娟
二〇一四年九月
1、实验目的
理解线性结构的定义、组织形式、结构特征和类型说明以及在链式存储方式下实现的插入、删除和按值查找的算法。
2、实验内容
线性表的链式表示和实现
3、实验程序
根据给出的程序清单分别另建立4个文件:
c1.h、c2-2.h、bo2-2.cpp和main2-2.cpp,并把它们保存在同一个文件夹中。
1.预定义常量和类型
教材定义OK、ERROR等为函数结果状态代码,文件Status为其类型。
我们把这些信息放到头文件c1.h中。
c1.h还包含一些常用的,如string.h、stdio.h等。
为了操作的方便,几乎每一个程序都把C1.h包含进去,也就把这些结果状态代码和头文件包含了进去。
头文件的内容如下:
//c1.h(程序名)
#include
#include
#include//malloc()等
#include//INT_MAX等
#include//EOF(=^Z或F6),NULL
#include//atoi()
#include//eof()
#include//floor(),ceil(),abs()
#include//exit()
#include//cout,cin
//函数结果状态代码
#defineTRUE1
#defineFALSE0
#defineOK1
#defineERROR0
#defineINFEASIBLE-1
//#defineOVERFLOW-2因为在math.h中已定义OVERFLOW的值为3,故去掉此行
//#defineOVERFLOW-2因为在math.h中已定义OVERFLOW的值为3,故去掉此行
typedefintStatus;//Status是函数的类型,其值是函数结果状态代码,如OK等
typedefintBoolean;//Boolean是布尔类型,其值是TRUE或FALSE
2、线性链表的单链表存储结构
//c2-2.h线性表的单链表存储结构
structLNode
{
ElemTypedata;
LNode*next;
};
typedefLNode*LinkList;//另一种定义LinkList的方法
3、单链表线性表的基本操作
//bo2-2.cpp单链表线性表(存储结构由c2-2.h定义)的基本操作(12个)
StatusInitList(LinkList&L)
{//操作结果:
构造一个空的线性表L
L=(LinkList)malloc(sizeof(LNode));//产生头结点,并使L指向此头结点
if(!
L)//存储分配失败
exit(OVERFLOW);
L->next=NULL;//指针域为空
returnOK;
}
StatusDestroyList(LinkList&L)
{//初始条件:
线性表L已存在。
操作结果:
销毁线性表L
LinkListq;
while(L)
{
q=L->next;
free(L);
L=q;
}
returnOK;
}
StatusClearList(LinkListL)//不改变L
{//初始条件:
线性表L已存在。
操作结果:
将L重置为空表
LinkListp,q;
p=L->next;//p指向第一个结点
while(p)//没到表尾
{
q=p->next;
free(p);
p=q;
}
L->next=NULL;//头结点指针域为空
returnOK;
}
StatusListEmpty(LinkListL)
{//初始条件:
线性表L已存在。
操作结果:
若L为空表,则返回TRUE,否则返回FALSE
if(L->next)//非空
returnFALSE;
else
returnTRUE;
}
intListLength(LinkListL)
{//初始条件:
线性表L已存在。
操作结果:
返回L中数据元素个数
inti=0;
LinkListp=L->next;//p指向第一个结点
while(p)//没到表尾
{
i++;
p=p->next;
}
returni;
}
StatusGetElem(LinkListL,inti,ElemType&e)//算法2.8
{//L为带头结点的单链表的头指针。
当第i个元素存在时,其值赋给e并返回OK,否则返回ERROR
intj=1;//j为计数器
LinkListp=L->next;//p指向第一个结点
while(p&&j
{
p=p->next;
j++;
}
if(!
p||j>i)//第i个元素不存在
returnERROR;
e=p->data;//取第i个元素
returnOK;
}
intLocateElem(LinkListL,ElemTypee,Status(*compare)(ElemType,ElemType))
{//初始条件:
线性表L已存在,compare()是数据元素判定函数(满足为1,否则为0)
//操作结果:
返回L中第1个与e满足关系compare()的数据元素的位序。
//若这样的数据元素不存在,则返回值为0
inti=0;
LinkListp=L->next;
while(p)
{
i++;
if(compare(p->data,e))//找到这样的数据元素
returni;
p=p->next;
}
return0;
}
StatusPriorElem(LinkListL,ElemTypecur_e,ElemType&pre_e)
{//初始条件:
线性表L已存在
//操作结果:
若cur_e是L的数据元素,且不是第一个,则用pre_e返回它的前驱,
//返回OK;否则操作失败,pre_e无定义,返回INFEASIBLE
LinkListq,p=L->next;//p指向第一个结点
while(p->next)//p所指结点有后继
{
q=p->next;//q为p的后继
if(q->data==cur_e)
{
pre_e=p->data;
returnOK;
}
p=q;//p向后移
}
returnINFEASIBLE;
}
StatusNextElem(LinkListL,ElemTypecur_e,ElemType&next_e)
{//初始条件:
线性表L已存在
//操作结果:
若cur_e是L的数据元素,且不是最后一个,则用next_e返回它的后继,
//返回OK;否则操作失败,next_e无定义,返回INFEASIBLE
LinkListp=L->next;//p指向第一个结点
while(p->next)//p所指结点有后继
{
if(p->data==cur_e)
{
next_e=p->next->data;
returnOK;
}
p=p->next;
}
returnINFEASIBLE;
}
StatusListInsert(LinkListL,inti,ElemTypee)//算法2.9。
不改变L
{//在带头结点的单链线性表L中第i个位置之前插入元素e
intj=0;
LinkListp=L,s;
while(p&&j{
p=p->next;
j++;
}
if(!
p||j>i-1)//i小于1或者大于表长
returnERROR;
s=(LinkList)malloc(sizeof(LNode));//生成新结点
s->data=e;//插入L中
s->next=p->next;
p->next=s;
returnOK;
}
StatusListDelete(LinkListL,inti,ElemType&e)//算法2.10。
不改变L
{//在带头结点的单链线性表L中,删除第i个元素,并由e返回其值
intj=0;
LinkListp=L,q;
while(p->next&&j{
p=p->next;
j++;
}
if(!
p->next||j>i-1)//删除位置不合理
returnERROR;
q=p->next;//删除并释放结点
p->next=q->next;
e=q->data;
free(q);
returnOK;
}
StatusListTraverse(LinkListL,void(*vi)(ElemType))
//vi的形参类型为ElemType,与bo2-1.cpp中相应函数的形参类型ElemType&不同
{//初始条件:
线性表L已存在
//操作结果:
依次对L的每个数据元素调用函数vi()。
一旦vi()失败,则操作失败
LinkListp=L->next;
while(p)
{
vi(p->data);
p=p->next;
}
printf("\n");
returnOK;
}
4、检验b02-2.cpp的主程序
//main2-2.cpp检验bo2-2.cpp的主程序(与main2-1.cpp很像)
#include"c1.h"
typedefintElemType;
#include"c2-2.h"//与main2-1.cpp不同
#include"bo2-2.cpp"//与main2-1.cpp不同
Statuscomp(ElemTypec1,ElemTypec2)
{//数据元素判定函数(相等为TRUE,否则为FALSE)
if(c1==c2)
returnTRUE;
else
returnFALSE;
}
voidvisit(ElemTypec)//与main2-1.cpp不同
{
printf("%d",c);
}
voidmain()//除了几个输出语句外,主程和main2-1.cpp很像
{
LinkListL;//与main2-1.cpp不同
ElemTypee,e0;
Statusi;
intj,k;
i=InitList(L);
for(j=1;j<=5;j++)
i=ListInsert(L,1,j);
printf("在L的表头依次插入1~5后:
L=");
ListTraverse(L,visit);//依次对元素调用visit(),输出元素的值
i=ListEmpty(L);
printf("L是否空:
i=%d(1:
是0:
否)\n",i);
i=ClearList(L);
printf("清空L后:
L=");
ListTraverse(L,visit);
i=ListEmpty(L);
printf("L是否空:
i=%d(1:
是0:
否)\n",i);
for(j=1;j<=10;j++)
ListInsert(L,j,j);
printf("在L的表尾依次插入1~10后:
L=");
ListTraverse(L,visit);
GetElem(L,5,e);
printf("第5个元素的值为:
%d\n",e);
for(j=0;j<=1;j++)
{
k=LocateElem(L,j,comp);
if(k)
printf("第%d个元素的值为%d\n",k,j);
else
printf("没有值为%d的元素\n",j);
}
for(j=1;j<=2;j++)//测试头两个数据
{
GetElem(L,j,e0);//把第j个数据赋给e0
i=PriorElem(L,e0,e);//求e0的前驱
if(i==INFEASIBLE)
printf("元素%d无前驱\n",e0);
else
printf("元素%d的前驱为:
%d\n",e0,e);
}
for(j=ListLength(L)-1;j<=ListLength(L);j++)//最后两个数据
{
GetElem(L,j,e0);//把第j个数据赋给e0
i=NextElem(L,e0,e);//求e0的后继
if(i==INFEASIBLE)
printf("元素%d无后继\n",e0);
else
printf("元素%d的后继为:
%d\n",e0,e);
}
k=ListLength(L);//k为表长
for(j=k+1;j>=k;j--)
{
i=ListDelete(L,j,e);//删除第j个数据
if(i==ERROR)
printf("删除第%d个数据失败\n",j);
else
printf("删除的元素为:
%d\n",e);
}
printf("依次输出L的元素:
");
ListTraverse(L,visit);
DestroyList(L);
printf("销毁L后:
L=%u\n",L);}
四、实验结果(截图)
5、实验总结
通过本次实验,我们对前一阶段的所学知识进行了巩固和提高,在对上节实验课的知识进行了消化吸收的基础上,理解线性结构的定义、组织形式、结构特征和类型说明以及在链式存储方式下实现的插入、删除和按值查找的算法。
《数据结构基础》是一门纯属于设计的科目,它需用把理论变为上机调试。
刚开始学的时候确实有很多地方我们很不理解,对于我们一个初学者来说,无疑是一个具大的挑战,顺着老师的思路,我们完成自己的设计,我们可以开始运行自己的程序,在实践中检验自己所学会的知识。