《数据结构与算法》实验指导书版.docx
《《数据结构与算法》实验指导书版.docx》由会员分享,可在线阅读,更多相关《《数据结构与算法》实验指导书版.docx(65页珍藏版)》请在冰豆网上搜索。
《数据结构与算法》实验指导书版
《数据结构与算法》实验指导书
大连民族学院
信息与通信工程学院
2013年10月10日
基本要求
1.学生必须按时到实验室做实验,不得迟到早退,未经老师批准不得中途离开。
凡迟到者,应给予批评并作适当扣分。
实验课迟到20分钟以上及无故缺席者视为旷课,旷课者不予补做实验,本次实验以零分计。
学生因病或特殊情况不能按时到实验室做实验时,应办理正常请假手续。
请病假必须有医生签字的病假条,请事假必须有班主任签字的事假条。
不符合请假手续的,以旷课论处。
请假的学生由指导教师安排补做实验。
对于未做实验数达三分之一以上(含三分之一)的学生,实验课程按0分计。
2.学生在每次实验课之前,应仔细阅读实验教材,查阅相关的资料,写出预习报告。
预习报告的具体内容包括:
实验内容、实验目的、实验原理图、实验步骤、实验数据记录表格等。
实验课前由任课教师检查预习报告,未写预习报告者不予做实验。
3.做实验前,了解设备的原理和正确使用方法。
在没有弄懂仪器设备的使用方法前,不得贸然使用,否则因使用不当造成仪器设备损坏的,根据大连民族学院《仪器设备损坏丢失处理暂行办法》规定进行处理。
实验室内设备在实验过程中不准任意搬动和调换,非本次实验所用仪器设备,未经指导教师允许不得动用。
4.要求每位学生在实验过程中,要具有严谨的学习态度、认真、踏实、一丝不苟的科学作风。
实验过程中学生按照预习的内容进行实验,且重视实验的调试过程,学会如何根据实验现象判断问题所在。
坚持每次实验都要亲自动手,不可“坐车”,每个实验每个学生都要独立完成,不允许抄袭,无特殊原因,中途不得退出实验,否则本次实验无效。
5.实验中若接线、改接、拆线都必须在切断电源的情况下进行,线路连接完毕再送电。
实验中,特别是设备刚投入运行时,要随时注意仪器设备的运行情况,如发现有过热、异味、冒烟、火花等,应立即断电,并请指导老师检查、处理。
6.实验过程中,如出现事故,就马上拉开电源开关,然后找指导教师和实验技术人员,如实反映事故情况,并分析原因和处理事故。
如有损坏仪表和设备时,应马上提出,按有关规定处理。
7.每次实验结束,指导教师要对实验数据和结果进行检查,并签字,在教师确认正确无误后,学生方可拆线。
整理好实验台和周围卫生,填写实验登记簿后方可离开。
8.每次实验后学生必须写出符合要求的实验报告,缺交者本次实验以零分计。
实验报告要求字迹工整、原始数据齐全、图表清晰、程序正确。
实验报告必须附有指导教师签字的原始数据表或预习报告,否则该实验报告无效。
为满足上述要求的按其程度扣除一定分值。
9.实验总评成绩评定:
每次实验后,教师根据学生的出勤、实验过程操作技能、实验原始记录、实验结果、实验报告等情况综合按5分制评分。
实验课考核不合格的学生按规定应重修该课程。
目录
绪论................................................................................................................................5
实验一:
线性表的结构定义及基本操作......................................................................6
实验二:
栈和队列的结构定义及基本操作...............................................................21
实验三:
二叉树的结构定义及基本操作....................................................................33
实验四:
图的结构定义及基本操作...........................................................................40
0绪论
本书是以《数据结构与算法》课程教学大纲和实验教学大纲为指导,分别从实验的六个方面(实验目的、实验内容、实验指导、参考程序、实验步骤以及思考题)来组织内容。
其中实验目的强调了每个实验要掌握的内容和要达到的层次;实验内容是对基本实验和扩展实验的问题进行描述,并且对实现要求进行了规划;实验指导对整个实验的结构进行了组织和指导;而参考程序则列出了实验要求中,特别是一些重要算法的参考描述;实验步骤则是指导学生进行实验的具体操作;思考题则是布置给学生对同类实验的一种思考和提示。
在参考程序中,主要实现了数据结构定义,基本操作和算法的验证。
其中:
在所有实验中我们建议采用VisualC++作为实验的开发环境,也可以用BC++,TC++环境以及C#,JAVA等其他语言。
如果用C环境,那么后面的参考程序中,凡是涉及到“引用”内容的,均要改为“指针”。
用VC++作为实验开发环境,首先建立Win32ConsoleApplication工程,其目的是在Windows图形环境中模拟DOS字符方式。
由于工程是以一组相关的文件组织的,将严格地按照文件内容的不同功能进行细致的划分,为了便于大家认真理解本指导书的内容,特对各
类文件的名称作了如下的规定:
文件名的标识基本以每个实验的内容作为依据,如顺序表的存储结构定义文件为SeqListDef.h。
这些程序文件主要包含了如下4类:
(1)pubuse.h是几乎所有实验中都涉及到的,包含了一些常量定义,系统函数原型声明和类型(Status)重定义,结果状态代码等。
在本文中的内容对某一个实验可能没有完全用到,但对本课程的其他实验可能有用;
(2)数据结构定义:
以____Def.h为文件名;
(3)基本操作和算法:
以____Algo.h为文件名;
(4)调用基本操作的主程序:
以_____Use.cpp为文件名。
实验一:
线性表的结构定义及基本操作(必做,2学时)
一、实验目的:
.掌握线性表的逻辑特征
.掌握线性表顺序存储结构的特点,熟练掌握顺序表的基本运算
.熟练掌握线性表的链式存储结构定义及基本操作
.加深对顺序存储数据结构的理解和链式存储数据结构的理解,逐步培养解决实际问题的编程能力
二、实验内容:
(一)基本实验内容(顺序表):
建立顺序表,完成顺序表的基本操作:
初始化、插入、删除、销毁、置空表、求表长、查找元素、判线性表是否为空;
1.问题描述:
利用顺序表,设计一组输入数据(假定为一组整数),能够对顺序表进行如下操作:
.创建一个新的顺序表,实现动态空间分配的初始化;
.根据顺序表结点的位置插入一个新结点(位置插入),也可以根据给定的值进行插入(值插入),形成有序顺序表;
.根据顺序表结点的位置删除一个结点(位置删除);
.彻底销毁顺序线性表,回收所分配的空间;
.对顺序线性表的所有元素删除,置为空表;
.返回顺序线性表数据元素个数;
.按序号查找,根据顺序表的特点,可以随机存取,直接可以定位于第i个结点,查找该元素的值,对查找结果进行返回;
.按值查找,根据给定数据元素的值,只能顺序比较,查找该元素的位置,对查找结果进行返回;
.判断顺序表中是否为空表,对判断结果进行返回;
.编写主程序,实现对各不同的算法调用。
2.实现要求:
对顺序表的各项操作一定要编写成为C(C++)语言函数,组合成模块化的形式,每个算法的实现要从时间复杂度和空间复杂度上进行评价;
.“初始化算法”的操作结果:
构造一个空的顺序线性表。
对顺序表的空间进行动态管理,实现动态分配、回收和增加存储空间;
.“位置插入算法”的初始条件:
顺序线性表L已存在,给定的元素位置为i,且1≤i≤ListLength(L)+1;
操作结果:
在L中第i个位置之前插入新的数据元素e,L的长度加1;
.“位置删除算法”的初始条件:
顺序线性表L已存在,1≤i≤ListLength(L);
操作结果:
删除L的第i个数据元素,并用e返回其值,L的长度减1;
.“销毁算法”初始条件:
顺序线性表L已存在;
操作结果:
销毁顺序线性表L;
.“置空表算法”初始条件:
顺序线性表L已存在;
操作结果:
将L重置为空表;
.“求表长算法”初始条件:
顺序线性表L已存在;
操作结果:
返回L中数据元素个数;
.“按序号查找算法”初始条件:
顺序线性表L已存在,元素位置为i,且1≤i≤ListLength(L)
操作结果:
返回L中第i个数据元素的值;
.“按值查找算法”初始条件:
顺序线性表L已存在,元素值为e;
操作结果:
返回L中数据元素值为e的元素位置;
.“判表空算法”初始条件:
顺序线性表L已存在;
操作结果:
若L为空表,则返回TRUE,否则返回FALSE;
分析:
修改输入数据,预期输出并验证输出的结果,加深对有关算法的理解。
(二)基本实验内容(链表):
建立单链表,完成链表(带表头结点)的基本操作:
建立链表、插入、删除和输出操作。
1.问题描述:
利用线性表的链式存储结构,设计一组输入数据(假定为一组整数),能够对单链表进行如下操作:
.初始化一个带表头结点的空链表;
.创建一个单链表是从无到有地建立起一个链表,即一个一个地输入各结点数据,并建立起前后相互链接的关系。
.插入结点根据给定位置进行插入(位置插入)。
.删除结点根据给定位置进行删除(位置删除)。
.输出单链表的内容是将链表中各结点的数据依次显示,直到链表尾结点。
.编写主程序,实现对各不同的算法调用。
其它的操作算法描述略。
2.实现要求:
对链表的各项操作一定要编写成为C(C++)语言函数,组合成模块化的形式,还要针对每个算法的
实现从时间复杂度和空间复杂度上进行评价。
.“初始化算法”的操作结果:
构造一个空的线性表L,产生头结点,并使L指向此头结点;
.“建立链表算法”初始条件:
空链存在;
操作结果:
选择逆位序或正位序的方法,建立一个单链表,并且返回完成的结果;
.“链表(位置)插入算法”初始条件:
已知单链表L存在;
操作结果:
在带头结点的单链线性表L中第i个位置之前插入元素e;
.“链表(位置)删除算法”初始条件:
已知单链表L存在;
操作结果:
在带头结点的单链线性表L中,删除第i个元素,并由e返回其值;
.“输出算法”初始条件:
链表L已存在;
操作结果:
依次输出链表的各个结点的值;
三、实验指导
一个简单程序通常主要由三部分构成:
1、常量定义(#define),类型重定义(typedef)及函数原型(#include)声明;还有针对每一种数据结构的类型定义,由于本实验是要求实现对线性表的顺序存储和链式存储两种存储结构的定义,因此不同的物理存储结构的定义和其基本操作最好是以独立的文件存在,因此本实验将顺序表和链表可分解为两个不同的实验部分。
2、算法函数,对于顺序表,每一个函数具有独立的功能,组合成为模块的形式,如ListInit_Sq、ListInsert_Sq、ListDelete_Sq、ListReverse_Sq、ListPrint_Sq等;对于链表,每一个函数具有独立的功能,组合成为模块的形式,如ListInit_Link、ListInsert_Link、ListDelete_Link等。
3、主函数(main)。
【说明1】――顺序表的定义与操作
1.可以将这三部分组合在一个文件中,也可以按照项目的方式(多个不同的文件组合在一起,共同完成一个功能)进行组织(本课程的实验强烈推荐这种形式),如将本课程后续所有算法几乎都要使用的常量定义(#define)和系统函数原型定义(#include)声明组合成一个文件,存储为一个头文件(取名为pubuse.h),只需建立一次,以后凡涉及到相关的内容,只需在你的文件的前面加上一条#include“pubuse.h”即可,无需重复输入。
2.对于类型定义,由于每一种数据结构的定义都不一样,因此要进行专门的类型定义,也可以将数据结构的定义组合成为一个文件,存储为一个头文件(如线性表的顺序存储结构定义取名为seqlistDef.h),只需建立一次,以后凡涉及到关于顺序表操作的相关内容,一定要在你的文件的前面加上一条#include“seqlistDef.h”即可,无需重复进行顺序存储结构的定义。
3.关于实验内容要完成的操作,一般都以独立的算法出现,关于某类数据结构的各种不同算法函数组合在一个文件之中,存储为一个头文件(如取名为seqlistAlgo.h),以后凡涉及到要使用本文件中的顺序表算法,一定要在你的文件的前面加上一条#include“seqlistAlgo.h”即可,无需重复定义类似的算法,就象使用系统函数一样,只需进行函数原型的声明即可。
4.还应包含一个main函数,作为整个程序的执行入口处,定义测试的数据,完成各种算法的调用执行,对算法的执行过程和结果进行判断和输出控制,存储为一个源文件(如取名为seqlistUse.cpp)。
5.为了对实际问题更加通用和适应,在算法中使用的数据类型为ElemType,为了与实际数据类型一致,一般要将ElemType用typedef重定义:
如实际问题中顺序表的每个元素是整型,则使用typedefintElemType;定义语句;如实际问题中顺序表的每个元素是单精度实数的话,使用typedeffloatElemType;定义语句。
【说明2】――链表的定义与操作
1.根据一个完整的C语言组成,将实验内容组合成如上所述的三个组成部分,功能清晰明了,其常量定义和常用系统函数原型声明的文件“pubuse.h”代码复用,不需另行建立。
2.建立一个单链表类型定义的头文件,如取名为:
linklistDef.h,以后凡使用该文件定义的类型,就只需使用包含语句#include“linklistDef.h”即可。
3.关于实验内容要完成的操作,一般都以独立的算法出现,建立一个单链表的基本算法文件,将各种不同算法组合在一个文件之中,存储为一个头文件如取名为:
linklistAlgo.h,后凡涉及到要使用本文件中的单链表算法,一定要在你的文件的前面加上一条#include“linklistAlgo.h”即可,实现的算法函数,如ListInit_Link、ListInsert_Link、ListDelete_Link、
等;
4.还应包含一个main函数,作为整个程序的执行入口处,定义测试的数据,完成各种算法的调用执行,对算法的执行过程和结果进行判断和输出控制,存储为一个源文件(如取名为linklistUse.cpp)。
四、基本实验的参考程序
(一)线性表的顺序存储结构的定义及其基本操作的参考程序(顺序表)
(1)文件1:
pubuse.h是公共使用的常量定义和系统函数调用声明,以后每个实验中几乎都涉及到此文件。
#include
#include
#include/*malloc()等*/
#include/*INT_MAX等*/
#include/*EOF(=^Z或F6),NULL*/
#include/*atoi()*/
#include/*eof()*/
#include/*floor(),ceil(),abs()*/
#include/*exit()*/
/*函数结果状态代码*/
#defineTRUE1
#defineFALSE0
#defineOK1
#defineERROR0
#defineINFEASIBLE-1
/*#defineOVERFLOW-2因为在math.h中已定义OVERFLOW的值为3,故去掉此行*/
typedefintStatus;/*Status是函数的类型,其值是函数结果状态代码,如OK等*/
typedefintBoolean;/*Boolean是布尔类型,其值是TRUE或FALSE*/
(2)文件2:
seqlistDef.h进行线性表的动态分配顺序存储结构的表示
#defineLIST_INIT_SIZE10/*线性表存储空间的初始分配量*/
#defineLISTINCREMENT2/*线性表存储空间的分配增量*/
typedefstruct
{
ElemType*elem;/*存储空间基址*/
intlength;/*当前长度*/
intlistsize;/*当前分配的存储容量(以sizeof(ElemType)为单位)*/
}SqList;
(3)文件3:
seqlistAlgo.h进行线性表顺序存储结构的基本实验算法定义
StatusListInit_Sq(SqList&L)/*算法2.3*/
{/*操作结果:
构造一个空的顺序线性表*/
L.elem=(ElemType*)malloc(LIST_INIT_SIZE*sizeof(ElemType));
if(!
L.elem)
exit(OVERFLOW);/*存储分配失败*/
L.length=0;/*空表长度为0*/
L.listsize=LIST_INIT_SIZE;/*初始存储容量*/
returnOK;
}
StatusListInsert_Sq(SqList&L,inti,ElemTypee)/*算法2.4*/
{/*初始条件:
顺序线性表L已存在,1≤i≤ListLength(L)+1*/
/*操作结果:
在L中第i个位置之前插入新的数据元素e,L的长度加1*/
ElemType*newbase,*q,*p;
if(i<1||i>L.length+1)/*i值不合法*/
returnERROR;
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;/*增加存储容量*/
}
q=L.elem+i-1;/*q为插入位置*/
for(p=L.elem+L.length-1;p>=q;--p)/*插入位置及之后的元素右移*/
*(p+1)=*p;
*q=e;/*插入e*/
++L.length;/*表长增1*/
returnOK;
}
StatusListDelete_Sq(SqList&L,inti,ElemType*e)/*算法2.5*/
{/*初始条件:
顺序线性表L已存在,1≤i≤ListLength(L)*/
/*操作结果:
删除L的第i个数据元素,并用e返回其值,L的长度减1*/
ElemType*p,*q;
if(i<1||i>L.length)/*i值不合法*/
returnERROR;
p=L.elem+i-1;/*p为被删除元素的位置*/
*e=*p;/*被删除元素的值赋给e*/
q=L.elem+L.length-1;/*表尾元素的位置*/
for(++p;p<=q;++p)/*被删除元素之后的元素左移*/
*(p-1)=*p;
L.length--;/*表长减1*/
returnOK;
}
StatusListPrint_Sq(SqListL)
{/*初始条件:
顺序线性表L已存在*/
/*操作结果:
依次对L的数据元素输出*/
inti;
printf("\n");
for(i=0;iprintf("%d",L.elem[i]);
returnOK;
}
/*StatusListDestroy_Sq(SqListL)
{/*初始条件:
顺序线性表L已存在*/
/*操作结果:
销毁顺序线性表L*/
/*Free(L.elem);
L.elem=NULL;
L.length=0;
L.listsize=0;
returnOK;
}*/
StatusListClear_Sq(SqListL)
{/*初始条件:
顺序线性表L已存在*/
/*操作结果:
将顺序线性表L重置为空表*/
L.length=0;
returnOK;
}
StatusListEmpty_Sq(SqListL)
{/*初始条件:
顺序线性表L已存在*/
/*操作结果:
若顺序线性表L为空表,则返回TRUE,否则返回FALSE*/
if(L.length==0)
returnTRUE;
//else
//returnFALSE;
}
StatusListGetElem_Sq(SqListL,inti,ElemType&e)
{/*初始条件:
顺序线性表L已存在,1≤i≤ListLength(L)*/
/*操作结果:
用e返回L中第i个数据元素的值*/
if(i<1||i>L.length)/*i值不合法*/
exit(ERROR);
e=*(L.elem+i-1);
returnOK;
}
/*还有一些算法,请同学们自己补充完整*/
(4)文件4:
seqlistUse.cpp进行线性表顺序存储结构的基本算法验证
#include"pubuse.h"/*实现通用常量的定义,常用系统函数的声明*/
typedefintElemType;/*实现一组整数的操作,将int型特定义为通用的ElemType类型名*/
#include"seqlistDef.h"/*采用线性表的动态分配顺序存储结构定义*/
#include"seqlistAlgo.h"/*采用顺序表的基本算法定义*/
voidmain()
{
SqListL;
Statusi;
intj;
intnum;
ElemTypet;
/*首先一定要初始化顺序表*/
i=ListInit_Sq(L);
if(i)
printf("成功地构造了一个空顺序表!
\n");
printf("请输入顺序表的长度j=");
scanf("%d",&j);
printf("请输入顺序表的元素(以空格为间隔)");
intm=j;
for(j=1;j<=m;j++)
{
scanf("%d",&num);
i=ListInsert_Sq(L,j,num);
}
ListPrint_Sq(L);/*输出表L的内容*/
intpos;
intval;
printf("\n请输入插入的位置和元素值(以,为间隔):
");
scanf("%d,%d",&pos,&val);
ListInsert_Sq(L,pos,val);/*随机指定插入