数据结构课程实验报告7.docx

上传人:b****8 文档编号:29574930 上传时间:2023-07-24 格式:DOCX 页数:54 大小:914.01KB
下载 相关 举报
数据结构课程实验报告7.docx_第1页
第1页 / 共54页
数据结构课程实验报告7.docx_第2页
第2页 / 共54页
数据结构课程实验报告7.docx_第3页
第3页 / 共54页
数据结构课程实验报告7.docx_第4页
第4页 / 共54页
数据结构课程实验报告7.docx_第5页
第5页 / 共54页
点击查看更多>>
下载资源
资源描述

数据结构课程实验报告7.docx

《数据结构课程实验报告7.docx》由会员分享,可在线阅读,更多相关《数据结构课程实验报告7.docx(54页珍藏版)》请在冰豆网上搜索。

数据结构课程实验报告7.docx

数据结构课程实验报告7

课程实验报告

课程名称:

数据结构

专业班级:

信安

学号:

姓名:

指导教师:

报告日期:

2015.4.5

计算机科学与技术学院

1课程实验概述

上机实验是对学生的一种全面综合训练,是与课堂听课、自学和练习相辅相成的必不可少的一个教学环节。

实验目的着眼于原理与应用的结合,使学生学会如何把书上的知识用语解决实际问题,能够理解和运用常用的数据结构,如线性表、栈、队列、树、图、查找表等,并在此基础上建立相应的算法;通过上机实验使学生了解算法和程序的区别,培养学生把算法转换为程序的能力,提高学生解决实际问题的能力;学会分析研究计算机加工的数据结构的特性,以便为应用涉及的数据选择适当的逻辑结构、存储结构及其相应的算法,并初步掌握算法的时间分析和空间分析的技术。

 

2实验一基于顺序结构的线性表实现

2.1问题描述

编写一个程序,实现顺序表的各种基本运算,并在此基础上完成以下功能:

 

1) 初始化顺序表; 

2)  释放顺序表;

3) 判断顺序表L是否为空; 

4) 输出顺序表L的长度;

5) 输出顺序表L的第i个元素; 

6) 输出元素e的位置; 

7) 输出元素e的前一个元素; 

8) 输出元素e的后一个元素; 

9) 在第i个元素位置上插入f元素; 

10)  删除L的第i个元素;

11) 输出顺序表L;

12) 保存顺序表L的数据。

2.2系统设计

1、数据类型

顺序表:

typedefstruct

{

ElemType*elem;//线性表首地址

intlength;//线性表当前长度

intlistsize;//线性表最大长度

}SqList;

数据类型:

int(可以在头文件中更改数据类型)

输入形式:

文件读取、键盘输入

输入范围:

-2^15~2^16

2、函数返回状态

判断为真:

TRUE0

判断为假:

FALSE-1

函数正确执行:

OK-2

函数执行错误:

ERROR-3

元素不存在:

NOTEXIST-4

内存分配溢出:

OVERFLOW-5

 

3、函数设计

InitList(&L) 

操作前提:

L是一个未初始化的线性表。

 

操作结果:

将L初始化为一个空的线性表。

 

DestroyList(&L) 

操作前提:

线性表L已存在。

 

操作结果:

销毁线性表L。

 

ListEmpty(L) 

操作前提:

线性表L已存在。

 

操作结果:

若L为空表,则返回TURE,否则返回FALSE。

 

ListLength(L) 

操作前提:

线性表L已存在。

 

操作结果:

返回L中数据元素个数。

 

GetElem(L, i,&e) 

操作前提:

线性表L已存在,1≤i≤ListLength(L)。

 

操作结果:

用e返回L中第i个元素的值。

 

LocateElem (L,e) 

操作前提:

线性表L已存在。

 

操作结果:

返回L中第一个e的位序。

 

若这样的数据元素不存在,则返回值为0。

PriorElem (L,e,&proi) 

操作前提:

线性表L已存在。

 

操作结果:

返回L中第一个e的前一个数据元素。

 

若这样的数据元素不存在,则返回值为0。

NextElem (L,e,&next) 

操作前提:

线性表L已存在。

 

操作结果:

返回L中第一个e的后一个的数据元素。

 

若这样的数据元素不存在,则返回值为0。

ListInsert (&L,i ,e) 

操作前提:

线性表L已存在,1≤i≤ListLength(L)+1。

 

操作结果:

在L中第i个位置之前插入新的数据元素e,L的长度+1。

 

ListDelete (&L,i, e) 

操作前提:

线性表L已存在且非空,1≤i≤ListLength(L)。

 

操作结果:

删除L的第i个元素数据,并用e返回其值,L的长度—1。

 

DisplayList(L) 

操作前提:

线性表L已存在。

 

操作结果:

打印表中元素。

SaveList(L)

操作前提:

线性表L已存在。

 

操作结果:

保存表中元素。

 

4、主要函数流程图

ProiElem:

这里的查找元素操作可直接调用LocateElem函数返回元素的位置,NextElem函数的流程图与此相似,这里不在赘述)

 

ListInsert:

这个函数最主要的部分就是检查参数与元素的移位操作,若参数不合法(传入空线性表、插入位置在线性表之外)极易出现访问数组外元素问题;元素移位操作要在不丢失数据的前提下(从最后一个元素开始)进行。

 

ListDelete

删除函数同样最主要的部分就是检查参数与元素的移位操作,若参数不合法(传入空线性表、删除位置在线性表之外)极易出现访问数组外元素问题;元素移位操作要在不丢失数据的前提下(从被删除的元素开始)进行。

2.3系统实现

这里也只给出主要函数的代码,完整代码会在附录给出

函数名:

LocateElem

参数:

线性表L、要查找的元素

返回值:

若元素存在,返回位置,否则返回错误信息

函数功能:

获取元素的位置

statusLocateElem(SqListL,ElemTypee)

{

if(!

L.elem)

returnERROR;

for(inti=1;i

{

if(e==L.elem[i])

returni;

}

returnNOTEXIST;

}

函数名:

PriorElem

参数:

线性表L、查找的元素、带回元素值的形参

返回值:

函数执行情况成功为OK,否则ERROR

函数功能:

获取元素的前继节点元素

statusPriorElem(SqListL,ElemTypecur,ElemType&pre_e)

{

/*不可获取线性表长度之外的元素,第0号元素不用*/

if(!

L.elem)

returnERROR;

intpos;

pos=LocateElem(L,cur);

if(pos<1)

returnERROR;

if(pos==1)

returnNOTEXIST;

pre_e=L.elem[pos-1];

returnOK;

}

 

函数名:

ListInsert

参数:

线性表L(引用)、要插入的位置及元素

返回值:

是否插入成功

函数功能:

插入元素到指定位置

statusListInsert(SqList&L,inti,ElemTypee)

{

/*不可获取线性表长度之外的元素,第0号元素不用*/

if(!

L.elem||i>L.length+1||i<1)

returnERROR;

if(L.length==L.listsize)

returnOVERFLOW;

for(intj=L.length+1;j>i;j--)

{

L.elem[j]=L.elem[j-1];

}

L.elem[i]=e;

L.length++;

returnOK;

}

函数名:

ListDelete

参数:

线性表L(引用)、位置、带回被删除的元素e

返回值:

是否删除元素成功

函数功能:

删除指定位置的元素并带回元素

statusListDelete(SqList&L,inti,ElemType&e)

{

/*不可获取线性表长度之外的元素,第0号元素不用*/

if(!

L.elem||i>L.length||i<1)

returnERROR;

e=L.elem[i];

for(intj=i;j

{

L.elem[j]=L.elem[j+1];

}

L.length--;

returnOK;

}

 

调试分析 

(1) 调试过程中主要遇到哪些问题?

是如何解决的?

 

调式过程中发现总是粗心大意忘了加分号或者打错字,所以学习C语言一定要细心仔细,不能着急。

 

用DisplayList函数时出现了问题,后来经过询问同学和查阅书本对程序进行了改正,使其能够正确进行。

 

(2) 经验和体会 

通过这次上机实验,对顺序表的各功能有了进一步的了解和学习,也对C语知识进行了巩固。

实验结果截图

实验测试数据为:

1、2、3、4、5、6、7、8、9。

这里依然只给出主要函数结果。

1)查找元素位置:

2)查找前继元素:

3)插入元素:

4)删除元素:

5)遍历线性表:

2.4效率分析

由于线性表具有随机访问的特性,所以线性表操作的时间基本来自于线性表的遍历、插入及删除操作。

假定线性表中有n个元素。

1)获取元素位置:

最好的情况:

第一个元素即为所要查找的元素,执行1次操作;

最坏的情况:

最后一个元素为要查找的元素,执行n次操作;

若所有元素访问的概率相等,则要执行(n+1)/2次操作。

总体来说时间复杂度为O(n)。

2)插入元素:

最好的情况:

插入到线性表尾,执行1次操作;

最坏的情况:

插入到线性表头,执行n次操作;

若所有元素访问的概率相等,则要执行(n+1)/2次操作。

总体来说时间复杂度为O(n)。

3)删除元素:

最好的情况:

删除线性表尾元素,执行1次操作;

最坏的情况:

删除线性表头元素,执行n次操作;

若所有元素访问的概率相等,则要执行(n+1)/2次操作。

总体来说时间复杂度为O(n)。

结果分析:

线性表比较适合经常访问但修改较少的实际运用。

3实验二基于链式结构的线性表实现

3.1问题描述

编写一个程序,实现线性链表的各种基本运算,并在此基础上完成以下功能:

 

1) 初始化线性链表; 

2)  释放线性链表;

3) 判断线性链表L是否为空; 

5) 输出线性链表L的长度;

5) 输出线性链表L的第i个元素; 

6) 输出元素e的位置; 

7) 输出元素e的前一个元素; 

8) 输出元素e的后一个元素; 

9) 在第i个元素位置上插入f元素; 

10)  删除L的第i个元素;

11) 输出线性链表L;

12) 保存线性链表L的数据。

3.2系统设计

1、数据类型

线性链表:

structLinkList

{

ElemTypedata;//链表元素

LinkList*next;//指向后继节点的指针

}

数据类型:

int(可以在头文件中更改数据类型)

输入形式:

文件读取、键盘输入

输入范围:

-2^15~2^16

2、函数返回状态

判断为真:

TRUE0

判断为假:

FALSE-1

函数正确执行:

OK-2

函数执行错误:

ERROR-3

元素不存在:

NOTEXIST-4

内存分配溢出:

OVERFLOW-5

 

3、函数设计

InitList(&L) 

操作前提:

L是一个未初始化的线性表。

 

操作结果:

将L初始化为一个空的线性表。

 

DestroyList(&L) 

操作前提:

线性表L已存在。

 

操作结果:

销毁线性表L。

 

ListEmpty(L) 

操作前提:

线性表L已存在。

 

操作结果:

若L为空表,则返回TURE,否则返回FALSE。

 

ListLength(L) 

操作前提:

线性表L已存在。

 

操作结果:

返回L中数据元素个数。

 

GetElem(L, i,&e) 

操作前提:

线性表L已存在,1≤i≤ListLength(L)。

 

操作结果:

用e返回L中第i个元素的值。

 

LocateElem (L,e) 

操作前提:

线性表L已存在。

 

操作结果:

返回L中第一个e的位序。

 

若这样的数据元素不存在,则返回值为0。

PriorElem (L,e,&proi) 

操作前提:

线性表L已存在。

 

操作结果:

返回L中第一个e的前一个数据元素。

 

若这样的数据元素不存在,则返回值为0。

NextElem (L,e,&next) 

操作前提:

线性表L已存在。

 

操作结果:

返回L中第一个e的后一个的数据元素。

 

若这样的数据元素不存在,则返回值为0。

ListInsert (&L,i ,e) 

操作前提:

线性表L已存在,1≤i≤ListLength(L)+1。

 

操作结果:

在L中第i个位置之前插入新的数据元素e,L的长度+1。

 

ListDelete (&L,i, e) 

操作前提:

线性表L已存在且非空,1≤i≤ListLength(L)。

 

操作结果:

删除L的第i个元素数据,并用e返回其值,L的长度—1。

 

DisplayList(L) 

操作前提:

线性表L已存在。

 

操作结果:

打印表中元素。

SaveList(L)

操作前提:

线性表L已存在。

 

操作结果:

保存表中元素。

 

4、主要函数流程图

NextElem:

这里的查找元素操作可直接调用LocateElem函数返回元素的位置,ProiElem函数的流程图与此相似,这里不在赘述)

 

ListInsert:

这个函数最主要的部分就是检查参数与节点的插入操作,若参数不合法(传入空线性链表、插入位置在线性链表之外)极易出现访问链表外元素问题;若插入首节点,要注意修改头指针,插入其他节点注意不要丢失指针,应先保存后继节点指针后,再修改前驱节点的后继。

ListDelete

删除函数同样最主要的部分就是检查参数与节点的删除操作,若参数不合法(传入空线性链表、删除位置在线性链表之外)极易出现访问链表外元素问题;若删除首节点,要先保存首节点的后继节点,再释放首地址,再修改头指针;删除其他节点要注意查找到它的前继节点,再修改前继节点的后继,释放节点。

3.3系统实现

这里也只给出主要函数的代码,完整代码会在附录给出

函数名:

LocateElem

参数:

线性表L、要查找的元素

返回值:

若元素存在,返回位置,否则返回错误信息

函数功能:

获取元素的位置

statusLink:

:

LocateElem(LinkL,ElemTypee)

{

if(L.head==NULL)

returnERROR;

intloc=0;

L.cur_p=head;

while(L.cur_p)

{

loc++;

if(L.cur_p->data==e)

returnloc;

L.cur_p=L.cur_p->next;

}

returnNOTEXIST;

}

函数名:

NextElem

参数:

线性表L、查找的元素、带回元素值的形参

返回值:

函数执行情况成功为OK,否则ERROR

函数功能:

获取元素的后继节点元素

statusLink:

:

NextElem(LinkL,ElemTypecur,ElemType&e)

{

if(L.head==NULL)

returnERROR;

intpos;

pos=LocateElem(L,cur);

if(pos<1)

returnERROR;

if(pos==L.length)

returnNOTEXIST;

GetElem(L,pos+1,e);

returnOK;

}

 

函数名:

ListInsert

参数:

线性表L(引用)、要插入的位置及元素

返回值:

是否插入成功

函数功能:

插入元素到指定位置

statusLink:

:

ListInsert(Link&L,inti,ElemTypee)

{

if(i<1||i>L.length+1)

returnERROR;

if(!

L.head)

{

L.head=(LinkList*)malloc(sizeof(LinkList));

if(!

L.head)

returnOVERFLOW;

L.head->data=e;

L.head->next=NULL;

L.length=1;

returnOK;

}

L.cur_p=L.head;

for(intj=1;j

{

L.cur_p=L.cur_p->next;

if(!

L.cur_p)

returnERROR;

}

L.tail=(LinkList*)malloc(sizeof(LinkList));

if(!

L.tail)

returnOVERFLOW;

L.tail->data=e;

if(i==1)

{

L.tail->next=L.head;

L.head=L.tail;

}

else

{

L.tail->next=L.cur_p->next;

L.cur_p->next=L.tail;

}

L.length++;

returnOK;

}

 

函数名:

ListDelete

参数:

线性表L(引用)、位置、带回被删除的元素e

返回值:

是否删除元素成功

函数功能:

删除指定位置的元素并带回元素

statusLink:

:

ListDelete(Link&L,inti,ElemType&e)

{

if(!

L.head||i<1||i>L.length)

returnERROR;

L.cur_p=L.head;

if(i==1)

{

L.head=L.head->next;

free(L.cur_p);

L.length--;

returnOK;

}

for(intj=1;j

{

L.cur_p=L.cur_p->next;

if(!

L.cur_p)

returnERROR;

}

L.tail=L.cur_p->next;

L.cur_p->next=L.cur_p->next->next;

free(L.tail);

L.tail=NULL;

L.length--;

returnOK;

}

 

调试分析 

(1) 调试过程中主要遇到哪些问题?

是如何解决的?

 

调式过程中发现总是无法插入到首节点,后来发现是没单独考虑首节点的插入操作。

用删除t函数时若删除第一个元素就出现异常退出,经调试发现操作的空指针,是未考虑删除首节点导致的。

 

(2) 经验和体会 

通过这次上机实验,对顺序链表的各功能有了进一步的了解和学习,也对C语知识进行了巩固。

实验结果截图

实验数据:

1、2、3、4、5、6、7、8、9

1)获取元素位置:

2)获取后继元素:

3)插入元素:

4)删除元素:

5)遍历线性链表:

3.4效率分析

由于线性链表不具有随机访问的特性,所以线性表操作的时间都来自于线性表的遍历操作。

假定线性表中有n个元素。

1)获取元素位置:

最好的情况:

第一个元素即为所要查找的元素,执行1次操作;

最坏的情况:

最后一个元素为要查找的元素,执行n次操作;

若所有元素访问的概率相等,则要执行(n+1)/2次操作。

总体来说时间复杂度为O(n)。

链式结构使得插入,删除操作不需要移动其他元素,只要更改指针指向,所以线性链表比较适合需要经常改动数据的结构,但同时也有一个问题,链表的空间使用效率不是很高,而且一个节点内存储的数据越少,利用率越低。

4实验三基于二叉链表的二叉树实现

4.1问题描述

编写一个程序,实现二叉树的各种基本运算,并在此基础上完成以下功能:

 

1) 初始化二叉树; 

2)  释放二叉树;

3) 判断二叉树是否为空; 

6) 输出二叉树的深度;

5) 先序遍历二叉树; 

6) 中序遍历二叉树; 

7) 后序遍历二叉树; 

8) 层序遍历二叉树; 

9) 在二叉树上插入f元素; 

10)  删除二叉树的元素e;

11) 保存二叉树的数据。

4.2系统设计

二叉树节点的定义

structBiTreeNode

{

ElemTypedata;//节点元素

BiTreeNode*parents;

BiTreeNode*Lson;//指向左后继节点的指针

BiTreeNode*Rson;//指向右后继节点的指针

};

队列,层序遍历二叉树时使用

structQueue

{

BiTreeNode*node;//保存二叉树节点

Queue*next;

};

1、数据类型

数据类型:

int(可以在头文件中更改数据类型)

输入形式:

文件读取、键盘输入

输入范围:

-2^15~2^16

 

2、函数返回状态

判断为真:

TRUE0

判断为假:

FALSE-1

函数正确执行:

OK-2

函数执行错误:

ERROR-3

元素不存在:

NOTEXIST-4

内存分配溢出:

OVERFLOW-5

3、函数设计

注:

所有函数在BiTree类中实现,所以函数没传根指针

InitBiTree() 

操作前提:

B是一个未初始化的二叉树。

 

操作结果:

将B初始化为一个空的二叉树。

 

DestroyBiTree() 

操作前提:

二叉树B已存在。

 

操作结果:

销毁二叉树B。

 

BiTreeEmpty() 

操作前提:

二叉树B已存在。

 

操作结果:

若B为空树,则返回TURE,否则返回FABSE。

 

BiTreeDepth() 

操作前提:

二叉树B已存在。

 

操作结果:

返回B的深度。

 

GetRoot() 

操作前提:

二叉树B已存在。

 

操作结果:

返回二叉树的根指针。

 

Value (e) 

操作前提:

二叉树B已存在,e是二叉树中的某个节点。

 

操作结果:

返回节点e的数据。

 

Assign (&e,valuei) 

操作前提:

二叉树B已存在,e是B中的一个节点。

 

操作结果:

节点e的值改为value。

 

Parent(e) 

操作前提:

二叉树B已存在,e是B中的一个节点。

 

操作结果:

返回e的双亲节点。

 

LeftChild(e) 

操作前提:

二叉树B已存在,e是B中的一个节点。

 

操作结果:

返回e的左子树根节点。

 

RightChild(e) 

操作前提:

二叉树B已存在,e是B中的一个节点。

 

操作结果:

返回e的右子树根节点。

 

LeftSibling(e) 

操作前提:

二叉树B已存在,e是B中的一个节点。

 

操作结果:

返回e的左兄弟节点,若e为B左子树,则返回空。

 

RightSibling(e) 

操作前提:

二叉树B已存在,e是B中的一个节点。

 

操作结果:

返回e的右兄弟节点,若e为B右子树,则返回空。

 

BiTreeInsert (e) 

操作前提:

二叉树B已存在。

 

操作结果:

在B中插入新的数据元素e。

 

BiTreeDeBete (e) 

操作前提:

二叉树B已存在且非空。

 

操作结果:

删除B的元素数据e。

 

PreOrderTraverse() 

操作前提:

二叉树B已存在。

 

操作结果:

先序遍历二叉树

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 自然科学 > 天文地理

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1