DS实验手册2.docx
- 文档编号:29429967
- 上传时间:2023-07-23
- 格式:DOCX
- 页数:35
- 大小:82.10KB
DS实验手册2.docx
《DS实验手册2.docx》由会员分享,可在线阅读,更多相关《DS实验手册2.docx(35页珍藏版)》请在冰豆网上搜索。
DS实验手册2
计算机科学与技术专业
数据结构
上机实验手册
台州学院数学与信息工程学院
计算机科学系
前言
上机实践是学生对所学知识的一种全面、综合的能力训练,是与课堂听讲、自学和练习相辅相成的必不可少的一个教学环节,也是对课堂教学与实践教学效果的一种检验。
通常,实验中的问题比理论课的习题复杂得多,也更接近实际。
实验课的内容一般着眼于原理与应用的结合,使学生学会如何把书上学到的知识运用于解决实际问题的过程中去,培养从事软件开发设计工作所必需的基本技能。
另一方面,能使书上的知识变活,起到深化理解和灵活掌握教学内容的目的。
理论课习题较偏重于如何编写功能单一的“小”算法,而实验是软件设计的综合训练,包括问题分析、总体结构设计、用户界面设计、程序设计基本技能、多人合作,以至一整套软件工程规范的训练和科学作风的培养。
此外,还有很重要的一点是:
机器是比任何教师都严格的把关者。
为了达到上述目的,本实验课程安排了9个独立的实验单元,各单元的训练重点在于基本数据结构的实现及其应用。
各实验单元与理论教学的各章具有紧密的联系,每个实验单元安排有难度不等的多个实验题,包括必做实验内容和选作实验内容,以便学生根据自己的实际情况选做部分实验内容。
每次上机实验前,要求同学们做好充分的准备,包括实验的目的要求、程序清单、测试数据和预计运算结果等,实验后写出完整的实验报告。
每份实验报告包括三部分内容:
实验目的和要求、实验内容及实验小结。
实验报告书写规范
实验报告包括三部分:
实验目的与要求
实验内容
实验小结
其中,实验内容包括:
实验题目
问题分析
程序清单
测试数据
调试分析
运行结果
实验一线性表及其应用
一、实验目的与要求
巩固对线性表逻辑结构的理解,熟练掌握线性表的两种存储结构及线性表的基本操作在两种存储结构上的实现,掌握以线性表作为数据结构解决实际问题的方法。
二、实验内容
(一)顺序表操作验证
1.问题描述
对以顺序存储结构存储的线性表,验证其插入、删除、查找、就地逆置等操作。
2.基本要求
用菜单实现操作选择。
3.测试数据
自拟。
(二)顺序表归并(选作)
1.问题描述
已知两顺序表SA、SB,其元素均为递增有序,将此两表归并成一个新的顺序表SC,并保持递增顺序。
2.基本要求
略。
3.测试数据
(1)顺序表A:
13679顺序表B:
2458。
(2)自拟。
4.实现提示
归并处理算法思想是:
依次扫描SA和SB中的元素,比较当前元素的值,将较小的元素赋给SC,直到一个顺序表扫描完毕,然后将另一个顺序表的余下的元素复制到SC中。
(三)单链表操作验证
1.问题描述
对以链式存储结构存储的线性表,验证其插入、删除、查找、求长度和就地逆置等操作。
2.基本要求
用菜单实现操作选择。
3.测试数据
自拟。
(四)单链表的应用(选作)
1.问题描述
某百货公司仓库中有一批电视机,按其价格从低到高的次序构成了一个单链表存于计算机中,链表的每个结点指出同样价格的电视机的台数。
现在又有m台价格为h元的电视机入库。
将新入库的电视机的相关数据加入链表中。
2.基本要求
注意价格在链表中是否已出现。
3.测试数据
自拟。
4.实现提示
链表结点至少包含三个域:
价格、数量和指针域,其结构可如下表示:
costnumnext
(五)一元多项式相加(选做)
1.问题描述
求两个一元多项式A(x)=a0+a1x+a2x2+…+anxn和B(x)=b0+b1x+b2x2+…+bmxm的和C(x)。
2.基本要求
算法输入为两个多项式中各项的系数和指数。
算法输出为多项式的和,参考输出格式:
7x^0+6x^1+1x^2+2x^4+4x^9+6x^11。
3.测试数据
(1)多项式A:
7+2x+5x3+4x9+6x11多项式B:
4x+x2-5x3+2x4
(2)自拟。
4.实现提示
(1)多项式的存储结构
多项式的每一项由其相应的系数和指数确定,各项间具有线性关系,因而可以采用线性表实现。
鉴于多项式非零项项数的不确定性,采用单链表存储更为恰当,多项式的每一个非零项对应链表中的一个结点,且链表中的结点从头到尾按指数递增有序排列。
多项式链表中的结点结构如下:
其中coef域存放项的系数,exp域存放项的指数,next域存放指向下一结点的指针。
(2)求两个多项式和的算法基本思想:
①定义三个指针分别指向三个多项式两多项式A(x)、B(x)和C(x)的链表中的当前结点。
②依次扫描多项式A链表和多项式B链表中各结点,作相应结点的指数比较。
若指数相等,则系数相加,相加后系数若不为0,则生成一个新结点,链入多项式和C的链表,相应指针后移。
若指数不相等,则对指数小的项生成一新结点,链入多项式和C的链表,相应指针后移。
这一过程直到A、B链表中有一个链表扫描完毕为止。
③将另一个未扫描完毕的多项式中剩余项结点链入和C的链表。
三、实验要求
本实验最低要求为在4个学时内完成实验内容
(一)和(四)。
实验二栈和队列及其应用
一、实验目的与要求
深入了解栈和队列的特性,以便在实际问题中灵活运用,巩固对这两种结构的构造方法的掌握。
二、实验内容
(一)栈操作的验证
1.问题描述
对于顺序栈、链栈的基本操作进行验证。
2.基本要求
考虑各种可能情况(包括溢出等)。
3.测试数据
自拟。
(二)队列操作的验证
1.问题描述
对于顺序队列、链队列的基本操作进行验证。
2.基本要求
考虑各种可能情况(包括溢出等)。
3.测试数据
自拟。
(三)队列元素倒置(选做)
1.问题描述
Q是一个非空队列,S是一个空栈。
实现将Q中元素倒置。
2.基本要求
仅使用栈和队列的基本操作及单个变量x。
3.测试数据
自拟。
4.实现提示
将队列中元素出队,入栈,再将栈中元素出栈并入队。
三、实验要求
本实验最低要求为在4个学时内完成实验内容
(一)和
(二)中一种存储结构下的操作验证。
四、应用举例
(一)利用队列解决分油问题
[问题描述]设有大小不等的三个无刻度的油桶,分别能盛满x,y,z公升油。
初始时,第一个油桶盛满油,第二、三个油桶为空,寻找一种最少步骤的分油方式,在某一个油桶上分出targ公升油。
[算法输入]三个油桶的盛油量,要分出的油量targ。
[算法输出]分油的结果。
[算法要点]分油过程中,由于油桶上没有刻度,只能将油桶倒满或者倒空。
三个油桶盛油的总量始终等于初始时第一个油桶盛满的油量。
算法的主要思想:
每次判断当前油桶是不是可以倒出油,以及其他某个油桶是不是可以倒进油。
如果满足以上条件,那么当前油桶的油或全部倒出,或将另一油桶倒满,针对两种不同的情况作不同的处理。
使用一个队列p,记录每次分油时各个油桶的盛油量和倒油过程等信息,队列中只记录互不相同的盛油状态(各个油桶的盛油量)。
如果列举出倒油过程的所有不同的盛油状态,经考察全部状态后,未能分出targ公升油的情况,就确定这个分油问题无解。
队列p通过指针he和ta实现倒油过程的控制。
1、算法
(1)数据类型定义
typedefstruct
{
intst[4];
intsb,eb;
intlast;
}object;
objectp[100];
intfu[4];
intq[100];
(2)分油算法
voidfenyou()
{
intw[4],w1[4];
inthe,ta,i,j,k,m,re,targ,fo,un,bo;
printf("输入各油桶盛油量\n");
printf("1:
");//输入油桶盛油量
scanf("%d",&fu[1]);
printf("\n");
printf("2:
");
scanf("%d",&fu[2]);
printf("\n");
printf("3:
");
scanf("%d",&fu[3]);
printf("\n");
printf("要分出的油量:
");//输入要分出的油量
scanf("%d",&targ);
printf("\n");
fo=FALSE;//标志,TRUE表示分油成功,FALSE表示分油失败
un=FALSE;
he=1;//he队列的头指针,ta队列的尾指针
ta=1;
p[1].st[1]=fu[1];//油桶初始状态:
1满,2、3空
p[1].st[2]=0;
p[1].st[3]=0;
p[1].sb=1;
p[1].eb=1;
p[1].last=1;
do
{//分油过程
w[1]=p[he].st[1];
w[2]=p[he].st[2];
w[3]=p[he].st[3];
i=0;
while((i<3)&&(!
fo)&&(!
un))
{
i=i+1;
if(w[i]>0)
{
j=0;
while((j<3)&&(!
fo)&&(!
un))
{
j=j+1;
if((w[j] =j)&&(! fo)) { w1[1]=w[1]; w1[2]=w[2]; w1[3]=w[3]; re=fu[j]-w[j]; if(w[i]>re) { w1[j]=fu[j]; w1[i]=w[i]-re; } else { w1[i]=0; w1[j]=w[j]+w[i]; } bo=FALSE; k=1; while((k<=ta)&&(! bo)) { bo=TRUE; for(m=1;m<=3;m++) if(w1[m]! =p[k].st[m]) bo=FALSE; k=k+1; } if(! bo) { ta=ta+1;//分油的一个步骤入队 p[ta].st[1]=w1[1]; p[ta].st[2]=w1[2]; p[ta].st[3]=w1[3]; p[ta].sb=i; p[ta].eb=j; p[ta].last=he; for(m=1;m<=3;m++) if(w1[m]==targ) fo=TRUE; } } } } } if(! fo) { he=he+1; if(he>ta) un=TRUE; } }while(! fo&&! un); printf("分油过程: \n"); if(! fo)//分油失败 printf("失败"); else//分油成功,将分油过程的步骤依次输出 { k=0; i=ta; while(i! =1) { k=k+1; q[k]=i; i=p[i].last; } for(;k>=1;k--) { printf("%2d->%2d",p[q[k]].sb,p[q[k]].eb); printf("%3d%3d%3d",p[q[k]].st[1],p[q[k]].st[2],p[q[k]].st[3]); printf("\n"); } } } 2、程序 #include typedefstruct { intst[4]; intsb,eb; intlast; }object; objectp[100]; intfu[4]; intq[100]; //各算法清单同前 voidmain() { fenyou(); } 3、测试数据 三个油桶盛油量分别为: 805030 要分出的油量为: 40 4、程序运行结果 分油过程: 1->230500 2->3302030 3->160200 2->360020 1->2105020 2->3104030 (二)迷宫问题 [问题描述]编写一个程序求解迷宫问题。 迷宫是一个如图2.6所示的m行n列的0、1矩阵,其中0表示无障碍,1表示有障碍。 设入口为(1,1),出口为(m,n),每次移动只能从一个无障碍的单元移到其周围8个方向上任一无障碍的单元,编制程序给出一条通过迷宫的路径或报告一个“无法通过”的信息。 [算法输入]代表迷宫人口的坐标(默认取1,1)。 [算法输出]穿过迷宫的结果,两种情况之一: ①穿越成功,输出路径; ②穿越失败,给出提示。 [算法要点] 要寻找一条通过迷宫的路径,就必须进行试探性搜索,只要有路可走就前进一步,无路可走时,退回一步,重新选择未走过的可走的路,如此继续,直至到达出口或返回入口(无法通过迷宫)。 可使用如下的数据结构: mg[1..m,1..n]表示迷宫,为避免在走迷宫时出界,将迷宫数组的边界以1包围起来,所以一个m×n大小的迷宫,则需要一个(m+2)×(n+2)大小的数组表示,即mg[0..m+1,0..n+1]表示迷宫,用数组zx,zy分别表示X,Y方向的移动增量,其值如表2.1所示。 在探索前进路径时,需要将搜索的踪迹记录下来,记录的踪迹应包含当前位置以及前趋位置。 在搜索函数中,将所有需要搜索的位置形成一个队列,将队列中的每一个元素可能到达的位置加入到队列中,当队列中某元素有可能到达的位置全部加入到队列之后,即从队列中将该元素去掉。 用变量front和rear分别表示队列的首与尾,当rear指示的元素已到达出口(m,n)时,根据rear所指示的前驱号可回溯得到走迷宫的最短路径。 表2.1zx,zy数组的方向取值 方向 北 东北 东 东南 南 西南 西 西北 下标 1 2 3 4 5 6 7 8 zx -1 -1 0 1 1 1 0 -1 zy 0 1 1 1 0 -1 -1 -1 入口 出口 图2.1迷宫示意图 1、算法 (1)类型定义 ①迷宫定义 intmg[m+2][n+2]; ②定义 structstype { intx,y,pre; }sq[400]; (3)方向数组定义 intzx[8],zy[8]; (2)操作算法 ①输出路径算法 voidprintpath(intrear) { inti,j; structstypep[100]; i=rear; do { printf("(%d,%d)",sq[i].r,sq[i].c); i=sq[i].pre; }while(i! =0); } ②走迷宫算法 voidmgpath() { inti,j,x,y,v,find,rear,front; sq[1].r=1; sq[1].c=1; sq[1].pre=0; find=0; j=0; front=1;//从(1,1)开始搜索 rear=1; mg[1][1]=-1; while(front<=rear&&! find) { x=sq[front].r; y=sq[front].c; for(v=0;v<8;v++)//循环扫描每个方向 { i=zx[v]+x;//选择一个前进方向(i,j) j=zy[v]+y; if(mg[i][j]==0)//如果该方向可走 { rear++;//进入队列 sq[rear].r=i; sq[rear].c=j; sq[rear].pre=front; mg[i][j]=-//避免搜索过的位置重复搜索 } if(i==m&&j==n)//找到了出口 { printpath(rear); find=1; } } front++; } if(! find)printf("不存在路径! "); } 2、程序 #include #definem8//m、n为迷宫的行、列数,可以自选 #definen8 structstype { intr,c,pre; }sq[400]; intmg[m+2][n+2]; intzx[8]={-1,-1,0,1,1,1,0,-1},zy[8]={0,1,1,1,0,-1,-1,-1}; //各算法清单同前 voidmain() { inti,j; printf("输入迷宫: "); for(i=0;i<=m+1;i++) { printf("第%d行: \n",i); for(j=0;j<=n+1;j++) scanf("%d",&mg[i][j]); } printf("输出迷宫: "); for(i=0;i<=m+1;i++) { for(j=0;j<=n+1;j++) printf("%d",mg[i][j]); printf("\n"); } printf("路径为: "); mgpath(); getch(); } 3、测试数据 迷宫为: 4、程序运行结果 输出迷宫: 1111111111 1001000101 1001000101 1000011001 1011100001 1000100001 1010001001 1011101101 1100000001 1111111111 路径为: (8,8)(7,8)(6,7)(5,6)(4,5)(3,4)(3,2)(2,2)(1,1) 说明: 此路径为逆序输出。 实验三串及其应用 一、实验目的与要求 熟悉串类型的实现方法,了解数据结构与实际问题处理的联系。 二、实验内容 (一)字符串操作验证 1.问题描述 验证字符串的基本操作。 2.基本要求 采用顺序结构存储串s。 3.测试数据 自拟。 (二)中心串对称问题 1.问题描述 对于给定的一个n个字符组成的字符串s,判断其是否为中心对称串。 若s=“c1,c2…ci,ci+1,…cn”满足如下条件: ①n必须是偶数。 ②假设j=n/2,则必有cj=cj+1,cj-1=cj+2,…c1=cn。 则称s为中心对称串。 2.基本要求 采用顺序结构存储串s。 3.测试数据 自拟。 4.实现提示 整个问题的求解可抓住以下重点: ①利用栈,将s的第一个字符至第n/2个字符进栈。 ②从s的后半部分中的第一个字符开始,与出栈字符比较.栈空且所有字符相等。 s是中心对称串。 三、实验要求 本实验最低要求为在4个学时内完成实验内容 (一)和 (二)。 实验四数组及其应用 一、实验目的与要求 熟练掌握数组的存储表示和实现技术以及稀疏矩阵的压缩存储技术,掌握在压缩存储基础上稀疏矩阵运算的实现。 二、实验内容 (一)矩阵的乘法 1.问题描述 A是m×n阶矩阵,B是n×k接矩阵,求A、B相乘的积C=A×B。 2.基本要求 采用数组存储矩阵。 3.测试数据 (1)矩阵A: 矩阵B: 乘积矩阵C: (2)自拟。 4.实现提示 若A是m×n阶矩阵,B是n×k接矩阵,则C是m×k接矩阵,其中: cmk=am1×b1k+am2×b2k+…+amn×bnk (二)稀疏矩阵相乘 1.问题描述 假设稀疏矩阵A和B(分别为m×n和n×l)采用三元组表示,计算C=A×B。 2.基本要求 要求C也采用稀疏矩阵的三元组表示。 3.测试数据 (1)矩阵A: 矩阵B: 乘积矩阵C: 204 000 001 (2)自拟。 4.实现提示 采用矩阵相乘的基本方法,关键是通过给定的行号i和列j找出原矩阵的对应元素值。 由于采用三元组作为存储结构,则三元组表中没有的元素值为0。 据此设计一个在三元组中查找元素值的函数,当在三元组中找到某元素时,返回其元素值,否则返回0。 利用该函数计算出C的行号i和列号j处的元素值,若该值不为0,则存入其三元组表示的矩阵中,否则不存入。 三、实验要求 本实验要求为在2个学时内完成实验内容 (一)和 (二)。 实验五树的基本操作 一、实验目的与要求 熟练掌握树的存储结构和基本操作,深入理解二叉树的建立及遍历操作的具体实现。 二、实验内容 (一)二叉树的基本操作 1.问题描述 建立二叉树,并分别按先序、中序和后序遍历这棵二叉树。 2.基本要求 以二叉链表作为存储结构。 3.测试数据 (1)A BC DEF (2)自拟。 4.实现提示 建立二叉链表的方法有很多,下面给出按层次顺序建立二叉链表的算法,按照完全二叉树的性质实现。 注意应严格按照完全二叉树的编号顺序输入数据。 例如,对于上图所示的二叉树,应输入“ABCΦDEF#”,其中@表示空,#为输入结束标志。 bitree*creatree() { bitree*Q[maxsize]; intfront,rear; charch; bitree*root,*s; root=NULL; front=1;rear=0;//置空队列 ch=getchar();//输入第一个字符 while(ch! ='#') { s=NULL; if(ch! ='@') { s=(bitree*)malloc(sizeof(bitree)); s->data=ch; s->lchild=NULL; s->rchild=NULL; } rear++; Q[rear]=s;//虚结点指针NULL或新结点地址入队 if(rear==1)//输入的第一个结点为根结点 root=s; else { if(s&&Q[front])//孩子和双亲结点均不是虚结点 if(rear%2==0) Q[front]->lchild=s;//新结点是左孩子 else Q[front]->rchild=s;//新结点是右孩子 if(rear%2==1) front++;//结点*Q[front]的两个孩子已处理完毕,出队列 } ch=getchar();//输入下一个字符 } returnroot;//返回根指针 } (二)二叉树的线索化 1.问题描述 对二叉树进行中序线索化。 2.基本要求 以二叉链表作为存储结构,并对该线索二叉树进行中序遍历。 3.测试数据 自拟。 三、实验要求 本实验要求为在4个学时内完成实验内容 (一)和 (二)。 实验六树的应用 一、实验目的与要求 通过应用树结构解决实际问题,掌握树的实际应用,从而将理论与实际结合起来。 二、实验内容 (一)借助二叉排序树实现排序 1.问题描述 对于给定的n个关键字值,采用二叉排序树方法对其
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- DS 实验 手册