数据结构课程实验报告7.docx
- 文档编号:29574930
- 上传时间:2023-07-24
- 格式:DOCX
- 页数:54
- 大小:914.01KB
数据结构课程实验报告7.docx
《数据结构课程实验报告7.docx》由会员分享,可在线阅读,更多相关《数据结构课程实验报告7.docx(54页珍藏版)》请在冰豆网上搜索。
数据结构课程实验报告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已存在。 操作结果: 先序遍历二叉树
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 数据结构 课程 实验 报告