实验手册文档格式.docx
《实验手册文档格式.docx》由会员分享,可在线阅读,更多相关《实验手册文档格式.docx(35页珍藏版)》请在冰豆网上搜索。
依次扫描SA和SB中的元素,比较当前元素的值,将较小的元素赋给SC,直到一个顺序表扫描完毕,然后将另一个顺序表的余下的元素复制到SC中。
(三)单链表操作验证
对以链式存储结构存储的线性表,验证其插入、删除、查找、求长度和就地逆置等操作。
(四)单链表的应用(选作)
1.问题描述
某百货公司仓库中有一批电视机,按其价格从低到高的次序构成了一个单链表存于计算机中,链表的每个结点指出同样价格的电视机的台数。
现在又有m台价格为h元的电视机入库。
将新入库的电视机的相关数据加入链表中。
注意价格在链表中是否已出现。
4.实现提示
链表结点至少包含三个域:
价格、数量和指针域,其结构可如下表示:
costnumnext
(五)一元多项式相加(选做)
求两个一元多项式A(x)=a0+a1x+a2x2+…+anxn和B(x)=b0+b1x+b2x2+…+bmxm的和C(x)。
算法输入为两个多项式中各项的系数和指数。
算法输出为多项式的和,参考输出格式:
7x^0+6x^1+1x^2+2x^4+4x^9+6x^11。
(1)多项式A:
7+2x+5x3+4x9+6x11多项式B:
4x+x2-5x3+2x4
(1)多项式的存储结构
多项式的每一项由其相应的系数和指数确定,各项间具有线性关系,因而可以采用线性表实现。
鉴于多项式非零项项数的不确定性,采用单链表存储更为恰当,多项式的每一个非零项对应链表中的一个结点,且链表中的结点从头到尾按指数递增有序排列。
多项式链表中的结点结构如下:
其中coef域存放项的系数,exp域存放项的指数,next域存放指向下一结点的指针。
(2)求两个多项式和的算法基本思想:
①定义三个指针分别指向三个多项式两多项式A(x)、B(x)和C(x)的链表中的当前结点。
②依次扫描多项式A链表和多项式B链表中各结点,作相应结点的指数比较。
若指数相等,则系数相加,相加后系数若不为0,则生成一个新结点,链入多项式和C的链表,相应指针后移。
若指数不相等,则对指数小的项生成一新结点,链入多项式和C的链表,相应指针后移。
这一过程直到A、B链表中有一个链表扫描完毕为止。
③将另一个未扫描完毕的多项式中剩余项结点链入和C的链表。
三、实验要求
本实验最低要求为在4个学时内完成实验内容
(一)和(四)。
实验二栈和队列及其应用
深入了解栈和队列的特性,以便在实际问题中灵活运用,巩固对这两种结构的构造方法的掌握。
(一)栈操作的验证
对于顺序栈、链栈的基本操作进行验证。
考虑各种可能情况(包括溢出等)。
(二)队列操作的验证
对于顺序队列、链队列的基本操作进行验证。
(三)队列元素倒置(选做)
Q是一个非空队列,S是一个空栈。
实现将Q中元素倒置。
仅使用栈和队列的基本操作及单个变量x。
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"
);
1:
"
//输入油桶盛油量
scanf("
%d"
&
fu[1]);
\n"
2:
fu[2]);
3:
fu[3]);
要分出的油量:
//输入要分出的油量
targ);
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<
j=j+1;
if((w[j]<
fu[j])&
(i!
=j)&
fo))
w1[1]=w[1];
w1[2]=w[2];
w1[3]=w[3];
re=fu[j]-w[j];
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])
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;
if(w1[m]==targ)
fo=TRUE;
}
fo)
he=he+1;
if(he>
ta)
un=TRUE;
}while(!
fo&
!
un);
分油过程:
fo)//分油失败
失败"
else//分油成功,将分油过程的步骤依次输出
k=0;
i=ta;
while(i!
=1)
q[k]=i;
i=p[i].last;
for(;
k>
=1;
k--)
%2d->
%2d"
p[q[k]].sb,p[q[k]].eb);
%3d%3d%3d"
p[q[k]].st[1],p[q[k]].st[2],p[q[k]].st[3]);
}
2、程序
#include<
stdio.h>
//各算法清单同前
voidmain()
fenyou();
3、测试数据
三个油桶盛油量分别为:
805030
要分出的油量为:
40
4、程序运行结果
分油过程:
1->
230500
2->
3302030
3->
160200
360020
1->
2105020
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
zy
入口
出口
图2.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;
(%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;
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++;
find)printf("
不存在路径!
#definem8//m、n为迷宫的行、列数,可以自选
#definen8
intr,c,pre;
intzx[8]={-1,-1,0,1,1,1,0,-1},zy[8]={0,1,1,1,0,-1,-1,-1};
voidmain()
输入迷宫:
for(i=0;
i<
=m+1;
i++)
第%d行:
i);
for(j=0;
j<
=n+1;
j++)
mg[i][j]);
输出迷宫:
mg[i][j]);
printf("
路径为:
mgpath();
getch();
迷宫为:
输出迷宫:
1111111111
1001000101
1000011001
1011100001
1000100001
1010001001
1011101101
1100000001
(8,8)(7,8)(6,7)(5,6)(4,5)(3,4)(3,2)(2,2)(1,1)
说明:
此路径为逆序输出。
实验三串及其应用
熟悉串类型的实现方法,了解数据结构与实际问题处理的联系。
(一)字符串操作验证
验证字符串的基本操作。
2.基本要求
采用顺序结构存储串s。
3.测试数据
(二)中心串对称问题
对于给定的一个n个字符组成的字符串s,判断其是否为中心对称串。
若s=“c1,c2…ci,ci+1,…cn”满足如下条件:
①n必须是偶数。
②假设j=n/2,则必有cj=cj+1,cj-1=cj+2,…c1=cn。
则称s为中心对称串。
采用顺序结构存储串s。
整个问题的求解可抓住以下重点:
①利用栈,将s的第一个字符至第n/2个字符进栈。
②从s的后半部分中的第一个字符开始,与出栈字符比较.栈空且所有字符相等。
s是中心对称串。
本实验最低要求为在4个学时内完成实验内容
(一)和
(二)。
实验四数组及其应用
熟练掌握数组的存储表示和实现技术以及稀疏矩阵的压缩存储技术,掌握在压缩存储基础上稀疏矩阵运算的实现。
(一)矩阵的乘法
A是m×
n阶矩阵,B是n×
k接矩阵,求A、B相乘的积C=A×
B。
采用数组存储矩阵。
(1)矩阵A:
矩阵B:
乘积矩阵C:
若A是m×
k接矩阵,则C是m×
k接矩阵,其中:
cmk=am1×
b1k+am2×
b2k+…+amn×
bnk
(二)稀疏矩阵相乘
假设稀疏矩阵A和B(分别为m×
n和n×
l)采用三元组表示,计算C=A×
要求C也采用稀疏矩阵的三元组表示。
204
000
001
采用矩阵相乘的基本方法,关键是通过给定的行号i和列j找出原矩阵的对应元素值。
由于采用三元组作为存储结构,则三元组表中没有的元素值为0。
据此设计一个在三元组中查找元素值的函数,当在三元组中找到某元素时,返回其元素值,否则返回0。
利用该函数计算出C的行号i和列号j处的元素值,若该值不为0,则存入其三元组表示的矩阵中,否则不存入。
本实验要求为在2个学时内完成实验内容
(一)和
(二)。
实验五树的基本操作
熟练掌握树的存储结构和基本操作,深入理解二叉树的建立及遍历操作的具体实现。
(一)二叉树的基本操作
建立二叉树,并分别按先序、中序和后序遍历这棵二叉树。
以二叉链表作为存储结构。
(1)A
BC
DEF
建立二叉链表的方法有很多,下面给出按层次顺序建立二叉链表的算法,按照完全二叉树的性质实现。
注意应严格按照完全二叉树的编号顺序输入数据。
例如,对于上图所示的二叉树,应输入“ABCΦDEF#”,其中@表示空,#为输入结束标志。
bitree*creatree()
{
bitree*Q[maxsize];
intfront,rear;
charch;
bitree*root,*s;
root=NULL;
rear=0;
//置空队列
ch=getchar();
//输入第一个字符
while(ch!
='
#'
)
s=NULL;
if(ch!
@'
{
s=(bitree*)malloc(sizeof(bitree));
s->
data=ch;
lchild=NULL;
rchild=NULL;
Q[rear]=s;
//虚结点指针NULL或新结点地址入队
if(rear==1)//输入的第一个结点为根结点
root=s;
if(s&
Q[front])//孩子和双亲结点均不是虚结点
if(rear%2==0)
Q[front]->
lchild=s;
//新结点是左孩子
rchild=s;
//新结点是右孩子
if(rear%2==1)
//结点*Q[front]的两个孩子已处理完毕,出队列
}
//输入下一个字符
returnroot;
//返回根指针
(二)二叉树的线索化
对二叉树进行中序线索化。
以二叉链表作为存储结构,并对该线索二叉树进行中序遍历。
本实验要求为在4个学时内完成实验内容
(一)和
(二)。
实验六树的应用
通过应用树结构解决实际问题,掌握树的实际应用,从而将理论与