数据结构实验报告.docx
- 文档编号:26994269
- 上传时间:2023-06-24
- 格式:DOCX
- 页数:47
- 大小:208.42KB
数据结构实验报告.docx
《数据结构实验报告.docx》由会员分享,可在线阅读,更多相关《数据结构实验报告.docx(47页珍藏版)》请在冰豆网上搜索。
数据结构实验报告
课程实验报告
课程名称:
数据结构课程实验
专业班级:
计算机科学技术
学号:
姓名:
指导教师:
祝建华
报告日期:
2015
计算机科学与技术学院
1课程实验概述
本次数据结构课程实验内容主要有:
1.基于顺序存储结构,实现线性表的基本的、常见的运算。
2.基于链式存储结构,实现线性表的基本的、常见的运算。
3.基于二叉链表,实现二叉树的的基本的、常见的运算。
本次实验的目的主要在于帮助学生熟悉和掌握数据结构中的一些基本概念,
如:
数据、数据项、数据元素、数据类型和数据结构等;掌握线性表的基本操作在两种存储结构上的实现、各种链表的操作和应用,以及掌握二叉树的基本操作,如:
插入、删除、遍历等。
从而巩固和加深对数据结构的理解,通过上机实验、调试程序,加深对课本知识的理解和算法的掌握,使学生能够熟练应用数据结构的知识编写程序,解决问题。
2实验一基于顺序存储结构的线性表实现
2.1问题描述
线性表是最数据结构中基本、最简单、也是最常用的一种数据结构。
线性表中数据元素之间的关系是一对一的关系,其逻辑结构简单,便于实现和操作。
因此,线性表这种数据结构在实际应用中是广泛采用的一种数据结构。
在本实验中,我们要建立一个基于顺序存储结构的线性表,来实现线性表的基本的,常见的运算,如线性表的创建、销毁、插入、删除等操作。
2.2系统设计
2.2.1本实验中提供了一个实现功能的演示系统,其中包含如下12种功能函数;
1.IntiaList7.LocatElem
2.DestroyList8.PriorElem
3.ClearList9.NextElem
4.ListEmpty10.ListInsert
5.ListLength11.ListDelete
6.GetElem12.ListTrabverse
0.Exit
2.2.2数据结构
typedefintstatus;
typedefstruct{
intitem1;
}Elemtype;
typedefstruct{
Elemtype*elem;
intlength;
intlistsize;
}SqList;
2.2.3各功能函数的实现
(1)IntiaList(*L)的功能
构造一个空线性表L,申请一个大小为LIST_INT_SIZE、类型为Elemtype的线性存储空间。
具体实现如下:
statusIntiaList(SqList*L){
//构造一个空的线性表L。
intn;
inti=0;
L->elem=(Elemtype*)malloc(LIST_INIT_SIZE*sizeof(Elemtype));
if(!
L->elem)exit(OVERFLOW);//存储分配失败
else{
L->length=0;//空表长度为0
L->listsize=LIST_INIT_SIZE;//初始存储容量
printf("请输入顺序表:
\n");
scanf("%d",&n);
while(n){
L->elem[i].item1=n;
i++;
L->length++;
L->listsize=L->listsize-4;
scanf("%d",&n);
}
returnOK;
}
}//IntiaLis
(2)DestroyList(*L)的功能
销毁头结点指针指向的线性存储空间,传入的是头结点地址。
具体实现如下:
statusDestroyList(SqList*L){
//销毁线性表L。
free(L->elem);
L->elem=NULL;
L->length=0;
L->listsize=0;
returnOK;
}
(3)ClearList(L)的功能
将线性表L置为空表,但是其不同于DestroyList(*L)的功能,ClearList(L)不会销毁物理存储空间。
具体实现如下:
statusClearList(SqListL){
//将L重置为空表。
L.length=0;
returnOK;
}
(4)ListEmpty(L)的功能
利用线性表的长度L.length来判断线性表L是否为空表。
若L为空,则返回TRUE;否则返回FALSE。
具体实现如下:
statusListEmpty(SqListL){
//若L为空,则返回TRUE;否则,返回FALSE。
if(!
L.length){
printf("\n线性表L为空表!
\n");
returnFALSE;
}
else{
printf("\n线性表L不是空表!
\n");
returnTRUE;
}
}
(5)ListLength(L)的功能
直接调用头结点的信息返回L中元素的个数。
具体实现如下:
intListLength(SqListL){
//返回L中元素的个数。
return++L.length;
}
(6)GetElem(L,i,*e)的功能
传入的是头结点值、元素位置i和节点位置。
具体实现如下:
statusGetElem(SqListL,inti,Elemtype*e){
//用e返回L中第i个数据元素的值。
if((i<1)||(i>L.length))returnERROR;//i值不合法
e->item1=(L.elem[i-1]).item1;
returnOK;
}
(7)LocatElem(L,e,compare())的功能
采用顺序遍历的方法从表头开始查找,一旦找到满足compare()关系的元素,则返回元素在该表中的位序,时间复杂度为O(n)。
具体实现如下:
statusLocatElem(SqListL,Elemtypee,status(*compare)(Elemtype,Elemtype)){
//返回L中第一个与e满足关系compare()的数据元素的位序;若这样的数据元素不存在,则返回0。
inti=0;
while(i ((*compare)(L.elem[i],e)))++i; if(i returni; printf("线性表L中第一个与e满足compare()关系的数据元素的位序为: %d\n",i); } elsereturn0; } (8)PriorElem(L,cur,*pre_e)的功能 实现此功能的关键在于定位元素cur,所以调用前面已经实现了的函数LocatElem(L,e,compare()),确定并返回既定元素的位置,时间复杂度为O(n)。 具体实现如下: statusPriorElem(SqListL,Elemtypecur,Elemtype*pre_e){ //若cur是L的数据元素,且不是第一个,则用pre_e返回它的前一个元素的内容;否则操作失败,pre_e无定义。 intj; if(j=LocatElem(L,cur,equal)){ if(j>1){ *pre_e=L.elem[j-2]; printf("cur的前一个元素为: %d",*pre_e); return1; } elseprintf("cur是L中的第一个元素! \n"); } elseprintf("cur不是L中的元素! \n"); } (9)NextElem(L,cur,*next_e)的功能 此功能的实现和PriorElem(L,cur,*pre_e)同理,利用LocatElem(L,e,compare())来定位元素。 具体实现如下: statusNextElem(SqListL,Elemtypecur,Elemtype*next_e){ //若cur是L的数据元素,且不是最后一个,则用next_e返回它的后一个元素的内容,否则操作失败,next_e无定义。 intj; if(j=LocatElem(L,cur,equal)){ if(j *next_e=L.elem[j+1]; printf("cur的后一个元素为: %d",*next_e); return1; } elseprintf("cur是L中的最后一个元素! \n"); } elseprintf("cur不是L中的元素! \n"); } (10)ListInsert(*L,i,e)的功能 在插入元素之前要检查存储空间,若已满,则需要再分配存储空间。 确定插入元素的位置之后,要先将第i个元素后面的所有元素都后移一个位置,空出位置之后再插入新元素e。 因为要进行移位操作,所以平均时间复杂度为O(n)。 具体实现如下: statusListInsert(SqList*L,inti,Elemtypee){ //在L中第i个元素之前插入新的数据元素e,L的长度加1。 //i的合法值为1<=i<=ListLength_Sq(L)+1 Elemtype*newbase; if((i<1)||i>L->length+1)returnERROR;//i值不合法 if(L->length>=L->listsize){//当前存储空间已满,再分配newbase=(Elemtype*)realloc(L->elem,(L->listsize+LISTINCREMENT)*sizeof(Elemtype)); if(! newbase)exit(OVERFLOW);//存储分配失败 L->elem=newbase;//新基址 L->listsize+=LISTINCREMENT;//增加存储空间 } intj=0; for(j=L->length;j>=i;j--) { (L->elem)[j]=(L->elem)[j-1]; } L->elem[i-1]=e; L->length++; return0; }//ListInsert (11)ListDelete(*L,i,*e)的功能 删除之前先要判断传入的元素编号是否合法,然后删除该元素e之后需要进行移位操作,平均时间复杂度为O(n)。 具体实现如下: statusListDelete(SqList*L,inti,Elemtype*e){ //删除L中第i个数据元素,并用e作为其返回值,L的长度减1。 //i的合法值为1<=i<=ListLength_Sq(L) if((i<1)||(i>L->length))returnERROR;//i值不合法 Elemtype*p,*q; p=&(L->elem[i-1]); e=p; q=L->elem+L->length-1; for(++p;p<=q;++p) *(p-1)=*p; --L->length; return0; }//ListDelete (12)ListTrabverse(L,visit())的功能 顺序遍历线性表,依次调用函数visit(),由遍历可知其时间复杂度为O(n)。 具体实现如下: statusListTrabverse(SqListL,void(*visit)(Elemtypee)){ //依次对L的每个数据元素调用函数visit()。 一旦visit()失败,则操作失败。 inti; if(! L.length)return(0); printf("\n-------------allelementsoflieartable----------------\n"); for(i=0;i return (1); } (13)equal(x,y)和display(e)功能 statusequal(Elemtypex,Elemtypey){ return(x.item1==y.item1); } voiddisplay(Elemtypee){ printf("%d",e.item1); } 2.3系统实现 2.3.1演示系统功能的实现,如图2.3.1所示 图2.3.1演示系统的实现 2.3.2构造线性表L(实现IntiaList(*L)的功能并输入该线性表元素),如图2.3.2所示 图2.3.2构造线性表L 2.3.3销毁线性表L(实现DestroyList(&L)的功能),如图2.3.3所示 图2.3.3销毁线性表L 2.3.4ClearList(L)、ListEmpty(L)的功能与DestroyList(&L)的功能类似,所以这里不作赘述。 2.3.5线性表L中的元素的个数(实现ListLength(L)的功能),如图2.3.5所示 图2.3.5返回线性表L中的元素个数 2.3.6GetElem(L,i,*e)的功能,如图2.3.6所示 图2.3.6返回线性表L中第i个元素的值 2.3.7LocatElem(L,e,compare())的功能,如图2.3.7所示 图2.3.7返回线性表L中第1个与元素e相等的元素的值 2.3.8PriorElem(L,cur,*pre_e)的功能,如图2.3.8所示 图2.3.8返回线性表L中cur的前一个元素的值 2.3.9NextElem(L,cur,*next_e)的功能,此功能的实现和PriorElem(L,cur,*pre_e)相似,所以这里不做赘述。 2.3.10ListInsert(*L,i,e)的功能,插入元素操作,如图2.3.10所示 图2.3.10在线性表L中第i个元素之前插入元素e 2.3.11ListDelete(*L,i,*e)的功能,此功能的实现和ListInsert(*L,i,e)相似,如图2.3.11所示 图2.3.11在线性表L中删除第i个元素 2.3.12ListTrabverse(L,visit())的功能,如图2.3.12 图2.3.12输出线性表L中所有元素的值 2.4效率分析 在上述系统设计环节,已经对各个函数功能的时间复杂度做了简单的分析。 (1)IntiaList(*L),DestroyList(&L),ClearList(L),ListEmpty(L)这几个功能的实现都比较简单,所以时间复杂度都为O (1); (2)GetElem(L,i,*e),LocatElem(L,e,compare()),PriorElem(L,cur,*pre_e),NextElem(L,cur,*next_e),ListInsert(*L,i,e),ListDelete(*L,i,*e),ListTrabverse(L,visit())这些函数功能因为要对线性表进行遍历,所以时间复杂度都为O(n). 3实验二基于链式结构的线性表实现 3.1问题描述 线性表是最数据结构中基本、最简单、也是最常用的一种数据结构。 线性表中数据元素之间的关系是一对一的关系,其逻辑结构简单,便于实现和操作。 因此,线性表这种数据结构在实际应用中是广泛采用的一种数据结构。 在本实验中,我们要建立一个基于链式存储结构的线性表,来实现线性表的基本的,常见的运算,如线性表的创建、销毁、插入、删除等操作。 3.2系统设计 3.2.1本实验中提供了一个实现功能的演示系统,其中包含如下12功能函数: 1.IntiaList7.LocatElem 2.DestroyList8.PriorElem 3.ClearList9.NextElem 4.ListEmpty10.ListInsert 5.ListLength11.ListDelete 6.GetElem12.ListTrabverse 0.Exit 3.2.2数据结构 typedefintstatus; typedefintElemType;//数据元素类型定义 typedefstructLNode{//顺序表(链式结构)的定义 ElemTypedata; structLNode*next; }LNode,*LinkList; 3.2.3各功能函数的实现 (1)IntiaList(LinkList&L)的功能; 构造一个空的线性表L。 申请一个大小为L=(LinkList)malloc(sizeof(LNode)),类型为LinkList的链式存储空间。 具体实现如下: statusIntiaList(LinkList&L){ //构造一个空的线性表 LinkListp; inti,n; ElemTypee; printf("\n请输入线性表L的元素个数: "); scanf("%d",&n); printf("\n请输入线性表L的数据元素: "); for(i=0;i scanf("%d",&e);//输入元素值 p=(LinkList)malloc(sizeof(LNode));//生成新结点 p->data=e; p->next=L->next; L->next=p; } if(! L)exit(OVERFLOW);//存储分配失败 returnOK; } (2)DestroyList(LinkList&L)的功能 销毁线性表,需要遍历该链表,算法的时间复杂度为O(n)。 具体实现如下: statusDestroyList(LinkList&L) { LinkListp,q;//p用于遍历链表,q指向待释放的元素 q=L; p=L->next; while(p) { free(q); q=p; p=p->next; } free(q); returnOK; } (3)ClearList(LinkList&L)的功能 将线性表L置为空表,但是其不同于DestroyList(*L),ClearList(L)不会销毁物理存储空间,这里也需要遍历线性表,所以算法的时间复杂度为O(n)。 具体实现如下: statusClearList(LinkList&L) { LinkListp,q; p=L->next; q=L->next; while(p) { p=p->next; free(q); q=p; } returnOK; } (4)ListEmpty(LinkListL)的功能 利用线性表的的长度L.length判断线性表L是否为空表。 若L为空,则返回TRUE;否则,返回FALSE。 具体实现如下: statusListEmpty(LinkListL) { //若L为空表,则返回TRUE;否则,返回FALSE if(L->next==NULL) returnTRUE; else returnFALSE; } (5)ListLength(LinkListL)的功能 遍历线性表得到线性表的长度,算法的时间复杂度为O(n)。 具体实现如下: intListLength(LinkListL) { //返回L中数据元素个数 LinkListp; intlength=0; p=L->next; while(p) { length++; p=p->next; } returnlength; } (6)GetElem(LinkListL,inti,ElemType&e)的功能 传入的是头结点值、元素位置i和节点位置。 具体实现如下: statusGetElem(LinkListL,inti,ElemType&e) { //L为带头结点的单链表的头指针 //当第i个元素存在时,其赋值给e并返回OK;否则,返回ERROR LinkListp; intj=1; p=L->next; while(p&&j p=p->next; ++j; } if(! p||j>i)returnERROR;//第i个元素不存在 e=p->data;//取第i个元素 returnOK; } (7)LocateElem(LinkListL,ElemTypee)的功能 采用遍历的方法从表头遍历查找,一旦找到满足compare()关系的元素,则返回元素的位序,时间复杂度为O(n)。 具体实现如下: statusLocateElem(LinkListL,ElemTypee) { //在线性表L中查找第一个值为e的元素 //若找到,则返回它在L中的位序,否则返回0 LinkListp; p=L->next; inti=0; while(p) { if(p->data==e){ i++; returni; } elsep=p->next; } return0; } (8)PriorElem(LinkListL,ElemTypecur,ElemType&pre_e)的功能 实现此功能的关键在于定位元素cur,利用遍历算法,确定并返回指定元素的位置,所以时间复杂度为O(n)。 具体实现如下: statusPriorElem(LinkListL,ElemTypecur,ElemType&pre_e) { //若cur是L的数据元素,且不是第一个,则用pre_e返回它的前驱,否则操作失败,pre_e无定义。 LinkListp; p=L; inti; if(p->next->data==cur){ printf("\ncur是L中的第一个元素! \n"); return0; } while(p) { if(p->next->data==cur) { pre_e=p->data; return1; } p=p->next; } return0;//操作失败,pre_e无定义 } (9)NextElem(L,cur,*next_e)的功能 此功能的实现和PriorElem(LinkListL,ElemTypecur,ElemType&pre_e)相似,也是利用遍历线性表来定位要查找的元素
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 数据结构 实验 报告
![提示](https://static.bdocx.com/images/bang_tan.gif)