数据结构实验报告.docx
《数据结构实验报告.docx》由会员分享,可在线阅读,更多相关《数据结构实验报告.docx(15页珍藏版)》请在冰豆网上搜索。
数据结构实验报告
课程设计报告
课程名称:
数据结构
专业班级:
计算机辅修一班
学号:
财大1309100108
姓名:
徐倬迅
指导教师:
袁凌
报告日期:
2015、6、23
计算机科学与技术
目录
实验一基于顺序结构的线性表实现1
1.1问题描述1
1.2系统设计1
1.3.系统实现2
1.4效率分析5
实验二基于链式结构的线性表实现5
2.1问题描述5
2.2系统设计5
2.3系统实现6
2.4效率分析10
四实验总结与评价10
实验一基于顺序结构的线性表实现
1.1问题描述
基于顺序存储结构,实现线性表的基本的、常见的运算。
1.2系统设计
1.2.1提供12个功能,分别是:
1.InitiaList
2.DestroyList
3.ClearList
4.ListEmpty
5.ListLength
6.GetElem
7.LocatElem
8.PriorElem
9.NextElem
10.ListInsert
11.ListDelete
12.ListTrabverse
1.2.2物理结构为顺序存储结构,数据元素为包含一个整型变量的结构体:
typedefstruct{
intitem1;
}Elemtype;
typedefstruct{
Elemtype*elem;
intlength;
intlistsize;
}SqList;
1.2.3构建线性表之前先声明一个头结点,用于存储该表的基本信息和首结点地址:
SqListL1,L2;//声明头结点
1.2.4文件预处理
#include
#include
#defineTRUE1;
#defineFALSE0;
#defineOK2;
#defineERROR-1;
#defineOVERFLOW-2;
typedefintstatus;
#defineLIST_INIT_SIZE100;
#defineLISTINCREMENT10;//预处理
1.3.系统实现
1.3.1InitialList功能
初始化线性表,传入的是头结点地址。
申请一个大小为LIST_INT_SIZE、类型为Elemtype的线性存储空间,并用头结点中的首结点指针指向该空间首地址。
具体实现如下:
statusIntiaList(SqList*L){
L->elem=(Elemtype*)malloc(LIST_INIT_SIZE*sizeof(Elemtype));
if(!
L->elem)
exit(OVERFLOW);
L->length=0;
L->listsize=LIST_INIT_SIZE;
returnOK;
}//IntiaList
1.3.2DestroyList功能
销毁头结点中首结点址针指向的线性存储空间,传入的是头结点地址。
具体实现如下:
statusDestroyList(SqList*L){
if(L->elem!
=NULL)
{
free(L->elem);
ResetSqList(L);
}
else
returnERROR;
returnOK;
}//DestroyList
1.3.3ClearList功能
与Destroy类似但是又有不同,ClearList并不销毁物理空间,而是修改逻辑关系值:
statusClearList(SqList*L){
if(L->elem==NULL)
returnERROR;
L->length=0;
returnOK;//ClearList
1.3.4ListEmpt功能
判空功能,判断表是否为空表。
传入的是头结点值,而非地址,因为不需要对头结点进行修改。
实现如下:
statusListEmpty(SqListL){
if(L.elem==NULL)
returnERROR;
if(0==L.length)
returnTRUE;
else
returnFALSE;//ListEmpty
1.3.5ListLenth功能
求表长功能,由于创建过程中已经把表长信息包含在头结点中,所以直接调用并显示即可:
intListLength(SqListL){
if(L.elem==NULL)
returnERROR;
returnL.length;
}//ListLenth
1.3.6GetElem功能
获取第i号元素,传入的是头结点值、元素编号i、以及出口表结点地址。
statusGetElem(SqListL,inti,Elemtype*e){
if(i<1||i>L.length)
returnERROR;
else{
*e=L.elem[i-1];
returnOK;
}
}//GetElem
1.3.7LocatElem功能
获取指定元素编号,传入头结点值、存储了所需元素信息的一个临时表结点值、equal函数地址。
采用顺序比较法从表头遍历并比较,一旦找到,返回编号i。
时间复杂度为
O(n)。
intLocatElem(SqListL,Elemtypee,status(*compare)(Elemtype,Elemtype)){
if(L.elem==NULL)
returnERROR;
inti;
for(i=L.lengthi>0i--)
{
if(compare(e,L.elem[i-1]))
returni;
}
return--i;
}//LocatElem
1.3.8PriorElem功能
求指定元素的前一个元素的内容,传入头结点值、包含指定元素信息的一个临时表结点值、存储前一个元素的表结点地址。
主要思路是先调用LocatElem确定指定元素的位置,如果不是首结点则可直接取到PriorElem的地址。
时间复杂度为O(n)。
具体实现如下:
statusPriorElem(SqListL,Elemtypecur,Elemtype*pre_e){
if(L.elem==NULL)
returnERROR;
inti=LocatElem(L,cur,equal);
if(i<=1)
returnERROR;
else{
assignEle(pre_e,L.elem[i-2]);
returnOK;
}
}//PriorElem
1.3.9NextElem功能
statusNextElem(SqListL,Elemtypecur,Elemtype*next_e){
if(L.elem==NULL)
returnERROR;
inti=LocatElem(L,cur,equal);
if(i==L.length&&i==0)
returnERROR;
else{
assignEle(next_e,L.elem[i]);
returnOK;
}
}//NextElem
1.3.10ListInsert功能
插入一个数据元素,传入头结点地址、插入位置i、临时表结点值。
在调用插入函数前构造一个临时表结点,用于存储数据元素信息。
进入插入子函数,插入前先判断插入位置是否合理,再判断是否“满载”。
如果满载则重新申请更大的存储空间。
接下来正式插入数据元素,“先空位置再插入”。
平均时间复杂度为
,O(n),n即listlenth。
statusListInsert(SqList*L,inti,Elemtypee){
if(i<1||i>L->length+1)
returnERROR;
if(L->length>=L->listsize)
{
Elemtype*newbase=(Elemtype*)realloc(L->elem,(L->listsize+LISTINCREMENT)*sizeof(Elemtype));
if(!
newbase)
exit(OVERFLOW);
L->elem=newbase;
L->listsize+=LISTINCREMENT;
}
Elemtype*insert=&(L->elem[i-1]);
Elemtype*cur=&(L->elem[L->length-1]);
for(cur>=insertcur--)
{
*(cur+1)=*cur;
}
*insert=e;
++L->length;
returnOK;
}//ListInsert
1.3.11ListDelete功能
statusListDelete(SqList*L,inti,Elemtype*e){
if(i<1||i>L->length)
returnERROR;
assignEle(e,L->elem[i-1]);
for(;ilength;i++)
{
L->elem[i-1]=L->elem[i];
}
--L->length;
returnOK;
}//ListDelete
1.3.12ListTraverse功能
statusListTrabverse(SqListL,void(*visit)(Elemtypee)){
inti;
if(!
L.length)
returnERROR;
for(i=0ivisit(L.elem[i]);
returnOK;
}//ListTraverse
1.4效率分析
由于在头结点结构体中已经包含了InitiaList、ListLength所需信息,所以效率为O
(1);
DestroyList、ClearList、ListEmpty、LocatElem、GetElem、PriorElem、NextElem、ListInsert、ListDelete、ListTraverse效率为O(n)。
实验二基于链式结构的线性表实现
2.1问题描述
基于链式存储结构,实现线性表的基本的、常见的运算。
2.2系统设计
2.2.1.同样提供12个功能
1.InitiaList
2.DestroyList
3.ClearList
4.ListEmpty
5.ListLength
6.GetElem
7.LocatElem
8.PriorElem
9.NextElem
10.ListInsert
11.ListDelete
12.ListTrabverse
2.2.2物理结构为链式结构,数据元素包含一个整型变量以及自身类型的指针
typedefstruct{
intitem1;
}Elemtype;
typedefstructLinkList{
Elemtypeele;
structLinkList*next;
}LinkList;
LinkList*L1=NULL;
LinkList*L2=NULL;//使用头结点的指针访问存有L1和L2数据的内存空间
2.2.3预处理
#include
#include//头文件
#defineTRUE1;
#defineFALSE0;
#defineOK2;
#defineERROR-1;
#defineOVERFLOW-2;
typedefintstatus;
#defineLIST_INIT_SIZE100;
#defineLISTINCREMENT10;
2.3系统实现
2.3.1InitiaList
由于链表的创建是动态的,因此初始化不需要创建一个巨大的存储空间。
statusIntiaList(LinkList**L)
{
(*L)=(LinkList*)malloc(sizeof(LinkList));
if(L==NULL)
exit(OVERFLOW);
(*L)->next=NULL;
(*L)->ele.item1=0;
returnOK;
}//IntiaList
2.3.2DestroyList
需要遍历链表,同时释放掉每个元素。
statusDestroyList(LinkList**L){
LinkList*p_prior;
if(*L==NULL)
returnERROR;
while(*L!
=NULL)
{
p_prior=(*L);
(*L)=(*L)->next;
free(p_prior);
}
*L=NULL;
returnOK;//DestroyList
2.3.3ClearList
由于链表不同于数序表,这里不仅要在逻辑上清空,还要在物理结构上清空,实现上与Destroy类似。
statusClearList(LinkList*L){
if(L==NULL)
returnERROR;
DestroyList(&L);
IntiaList(&L);
returnOK;
}//ClearList
2.3.4ListEmpty
判空操作,L.elem不为NULL即不空。
statusListEmpty(LinkList*L){
if(L==NULL)
returnERROR;
if(L->next==NULL)
returnTRUE;
else
returnFALSE;
}//ListEmpty
2.3.5ListLength
求表长,由于在插入元素的同时已经记录了表长信息,所以只要读取L.length即可。
intListLength(SqListL){
if(L.elem==NULL)
returnERROR;
returnL.length;
}//ListLenth
2.3.6GetElem
取第i号元素并用一个数据元素类型结构体指针传出其信息。
statusGetElem(SqListL,inti,Elemtype*e){
if(L.elem==NULL||1>i||L.length
returnERROR;
else{
assignEle(e,L.elem[i-1]);
returnOK;
}
}//GetElem
2.3.7LocatElem
基于遍历链表实现定位。
intLocatElem(SqListL,Elemtypee,status(*compare)(Elemtype,Elemtype)){
if(L.elem==NULL)
returnERROR;
inti;
for(i=L.lengthi>0i--)
{
if(compare(e,L.elem[i-1]))
returni;
}
return--i;
}//LocatElem
2.3.8PriorElem
基于遍历找到指定元素的前一个元素。
statusPriorElem(SqListL,Elemtypecur,Elemtype*pre_e){
if(L.elem==NULL)
returnERROR;
inti=LocatElem(L,cur,equal);
if(i<=1)
returnERROR;
else{
assignEle(pre_e,L.elem[i-2]);
returnOK;
}
}//PriorElem
2.3.9NextElem
与PriorElem思路同,不赘述。
statusNextElem(SqListL,Elemtypecur,Elemtype*next_e){
if(L.elem==NULL)
returnERROR;
inti=LocatElem(L,cur,equal);
if(i==L.length&&i==0)
returnERROR;
else{
assignEle(next_e,L.elem[i]);
returnOK;
}
}//NextElem
2.3.10ListInsert
插入一个新元素。
statusListInsert(SqList*L,inti,Elemtypee){
if(i<1||i>L->length+1)
returnERROR;
if(L->length>=L->listsize)
{
Elemtype*newbase=(Elemtype*)realloc(L->elem,(L->listsize+LISTINCREMENT)*sizeof(Elemtype));
if(!
newbase)
exit(OVERFLOW);
L->elem=newbase;
L->listsize+=LISTINCREMENT;
}
Elemtype*insert=&(L->elem[i-1]);
Elemtype*cur=&(L->elem[L->length-1]);
for(cur>=insertcur--)
{
*(cur+1)=*cur;
}
*insert=e;
++L->length;
returnOK;
}//ListInsert
2.3.11ListDelete
删除第i号元素。
statusListDelete(SqList*L,inti,Elemtype*e){
if(i<1||i>L->length)
returnERROR;
assignEle(e,L->elem[i-1]);
for(;ilength;i++)
{
L->elem[i-1]=L->elem[i];
}
--L->length;
returnOK;
}//ListDelete
2.3.12ListTraverse
顺序遍历链表。
statusListTrabverse(SqListL,void(*visit)(Elemtypee)){
inti;
if(!
L.length)
returnERROR;
for(i=0ivisit(L.elem[i]);
returnOK;
}//ListTraverse
2.4效率分析
由于在头结点结构体中已经包含了InitiaList、ListLength所需信息,所以效率为O
(1);
很多功能都基于遍历:
DestroyList、Clearlist、ListTraverse,效率为O(n);
GetElem、LocatElem、PriorElem、NextElem、ListInsert、ListDelete,平均效率也为O(n)。
四实验总结与评价
自己没有什么c语音基础,学这门课还是很累的,查了很多资料完成了这次实验,其中依然还有有很多半懂不懂的地方,如果有什么疏漏之处,希望老师谅解。
本次实验需要很细心,有一点点的出错都会导致程序调试失败,比如哪个地方多加了一个空格键都不行,写出来的程序中也有没有调试成功的地方。
终于体会到查不出问题的痛苦。
以后做这方面的实验也需要很细致,不能有马虎的地方。
最后实验终于在磕磕绊绊中完成了,真的写不出什么总结。
只想说,我还是去复习准备考试吧。