算法程序设计实验报告.docx
《算法程序设计实验报告.docx》由会员分享,可在线阅读,更多相关《算法程序设计实验报告.docx(26页珍藏版)》请在冰豆网上搜索。
算法程序设计实验报告
《程序设计》课程设计
姓名:
王
学号:
20100034
班级:
软件工程00班
指导教师:
王会青
成绩:
2010年6月
实验一.构造可以使n个城市连接的最小生成树
专业:
__软件工程___班级:
__软件姓名:
_王___学号:
_20100034
完成日期:
_2010/6/26________
一、【问题描述】
给定一个地区的n个城市间的距离网,用Prim算法或Kruskal算法建立最小生成树,并计算得到的最小生成树的代价。
1城市间的道路网采用邻接矩阵表示,邻接矩阵的存储结构定义采用课本中给出的定义,若两个城市之间不存在道路,则将相应边的权值设为自己定义的无穷大值。
2显示出城市间道路网的邻接矩阵。
3最小生成树中包括的边及其权值,并显示得到的最小生成树的总代价。
4输入城市数、道路数→输入城市名→输入道路信息→执行Kruskal算法→执行Prim算法→输出最小生成树
二、【问题分析】
1.抽象数据类型结构体数组的定义:
#ifndefADJACENCYMATRIXED//防止该头文件被重复引用
#defineADJACENCYMATRIXED//而引起的数据重复定义
#defineINFINITY32767//最大值∞
#defineMAX_VERTEX_NUM20//最大顶点个数
typedefintVRType;//权值,即边的值
typedefcharInfoType;//附加信息的类型,后面使用时会定义成一个指针
typedefcharVertexType[MAX_VERTEX_NUM];//顶点类型
typedefenum{DG=1,DN,UDG,UDN}GraphKind;//{有向图,有向网,无向图,无向网}
typedefstructArcCell
{
VRTypeadj;//VRType是顶点关系类型。
对无权图,用1或0表示相邻否;对带权图,则为权值类型。
InfoType*info;//该弧关系信息的指针
}ArcCell,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
typedefstruct
{
VertexTypevexs[MAX_VERTEX_NUM];//顶点向量
AdjMatrixarcs;//邻接矩阵
intvexnum,arcnum;//图的当前顶点数和弧数
GraphKindkind;//图的种类标志
}MGraph;
typedefstruct//普里姆算法辅助数组的定义
{
VertexTypeadjvex;
VRTypelowcost;
}closedge[MAX_VERTEX_NUM];
#endif//结束if
2程序模块
MGraphG;//网G,唯一的全局变量
intmain(intargc,char*argv[]);//主函数
StatusLocateVex(MGraphG,VertexTypev);//判断城市v在网G中的位置
StatusCreateUDN(MGraph&G);//创建网G的邻接矩阵
voidDisplayNet(MGraphG);//以邻接矩阵的形式显示网G
voidMiniSpanTree_KRUSKAL(MGraphG);//最小生成树的Kruskal算法
voidMiniSpanTree_PRIM(MGraphG,VertexTypeu);//最小生成树的Prim算法
StatusMinimum(closedgecloseEdge,intn);//Prim算法中求下一个城市的函数
voidDeleteInfo(MGraph&G);//释放堆内存上动态申请的空间
3.流程图
创建用邻接矩阵表示的城市道路网
输入城市数G.vexnum、
道路数G.arcnum
输入城市名G.vexs[i]
输入表示道路的两个城市及道路值G.arcs[i][j].adj
返回OK
Prim算法
化辅助数组closeEdge
for(i=1;i求下一个城市k=Minimum(closeEdge,G.vexnum)
输出找到的道路
标记城市,避免重复
输出总耗费
4.数据类型定义
为了用邻接矩阵表示图G,先是定义二维数组的每一个元素含道路值然后在图的定义中定义一个此二维数组的结构成员。
并且在图中还定义一个用来存放城市的一维数组及int型的城市数级道路数。
用二维数组的两个下标表示道路,这两个下标又在一位数组中对应两个城市。
这样就建立起了一个城市到城市之间的道路网。
4.程序主要模块
说明:
该程序共含5个模块,本人负责其中2个模块构造:
***************LocateVex(MGraphG,VertexTypev)****************
StatusLocateVex(MGraphG,VertexTypev);
{
while(strcmp(G.vexs[i],v)){i++;}
返回i;
}
****************CreateUDN*************************
{
输入城市数、道路数;
for(i=0;i<城市数;++i)输入城市名;
for(i=0;i<城市数;++i)
for(j=0;j<城市数;++j)
初始化邻接矩阵:
道路值=INFINITY;
for(i=0;i<城市数;++i)
for(j=0;j<城市数;++j)
输入两个城市表示道路,输入道路值;
}
PRIM算法
**************************MiniSpanTree_PRIM*********
voidMiniSpanTree_PRIM(MGraphG,VertexTypeu)
{
定义辅助数组:
closedgecloseEdge;
初始化:
strcpy(closeEdge[j].adjvex,u);
closeEdge[j].lowcost=G.arcs[k][j].adj;
for(i=1;i{
在其余G.vexnum-1个城市中找到离辅助数组中标记的道路最小值;
显示找到的道路;
标记新找到的城市;
}
}
**********************Minimum*****************
StatusMinimum(closedgecloseEdge,intn)
{
在辅助数组中找到道路值最小的道路的两点城市:
if((closeEdge[i].lowcost!
=0)&&(minTemp>closeEdge[i].lowcost))
返回该城市在G中的位置
}
三、【功能实现】
#include
#include
#include
#include
#include"TypeDefine.h"
#include"AdjacencyMatrix.h"
#include"InitializeFunction.h"
#include"MiniSpanTree_KRUSKAL.h"
#include"MiniSpanTree_PRIM.h"
#include"DisplayNet.h"
#include"DeleteInfo.h"
MGraphG;//全局变量G
intmain(intargc,char*argv[]);//主函数
StatusLocateVex(MGraphG,VertexTypev);//判断城市v在网G中的位置
StatusCreateUDN(MGraph&G);//创建网G的邻接矩阵
voidDisplayNet(MGraphG);//以邻接矩阵的形式显示网G
voidMiniSpanTree_KRUSKAL(MGraphG);//最小生成树的Kruskal算法
voidMiniSpanTree_PRIM(MGraphG,VertexTypeu);//最小生成树的Prim算法
StatusMinimum(closedgecloseEdge,intn);//Prim算法中求下一个城市的函数
voidDeleteInfo(MGraph&G);//释放堆内存上动态申请的空间
intmain(intargc,char*argv[])
{
CreateGraph(G);
DisplayNet(G);
MiniSpanTree_KRUSKAL(G);
MiniSpanTree_PRIM(G,G.vexs[0]);
DeleteInfo(G);
cout<system("pause");
return0;
}
//intializeFunction.h
StatusCreateDG(MGraph&G){return0;};
StatusCreateDN(MGraph&G){return0;};
StatusCreateUDG(MGraph&G){return0;};
StatusCreateUDN(MGraph&G);
StatusLocateVex(MGraphG,VertexTypev)
{
//判断输入的顶点v在G中的位置。
//根据顶点的类型,可重载此函数。
目前为char
inti=0;
while(strcmp(G.vexs[i],v)){i++;}
returni;
}
StatusCreateGraph(MGraph&G)
{
//采用数组(邻接矩阵)表示法,构造图G.
G.kind=UDN;//默认构造无向网
/*printf("+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
printf("|1:
有向图2:
无向图3:
有向网4:
无向网\n");
printf("|请选择:
[]\b\b");
scanf("%d",&G.kind);
printf("+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");*/
switch(G.kind)
{
caseDG:
returnCreateDG(G);//构造有向图G
caseDN:
returnCreateDN(G);//构造有向网G
caseUDG:
returnCreateUDG(G);//构造无向图G
caseUDN:
returnCreateUDN(G);//构造无向网G
default:
returnERROR;
}
}//CreateGraph
StatusCreateUDN(MGraph&G)
{
//采用数组(邻接矩阵)表示法,构造图G.
inti,j,k;
VertexTypev1,v2;
VRTypew;
printf("构造可以使N个城市连接的最小生成树\n");
printf("请输入城市数、道路数(至少6个城市,10条道路):
");
cin>>G.vexnum>>G.arcnum;
for(i=0;i{
printf("请输入第%d个城市名(共%d个):
",i+1,G.vexnum);
cin>>G.vexs[i];
}
for(i=0;i{
for(j=0;j{
G.arcs[i][j].adj=INFINITY;
//G.arcs[i][j].info=NULL;
}
}
printf("请输入一条道路连接的两个城市名及权值:
\n");
for(k=0;k{
printf("共%3d条道路,第%3d条道路:
",G.arcnum,k+1);
cin>>v1>>v2>>w;//输入一条边依附的顶点及权值
i=LocateVex(G,v1);//确定v1、v2在G中的位置
j=LocateVex(G,v2);
G.arcs[i][j].adj=w;//弧的权值
G.arcs[j][i]=G.arcs[i][j];//置的对称弧
}
returnOK;
}//CreateUDN
//MiniSpanTreePRIM.h
StatusMinimum(closedgecloseEdge,intn)
{
inti,flag,minTemp=INFINITY;
for(i=0;i{
if((closeEdge[i].lowcost!
=0)&&(minTemp>closeEdge[i].lowcost))
{
minTemp=closeEdge[i].lowcost;
flag=i;
}
}
returnflag;
}
voidMiniSpanTree_PRIM(MGraphG,VertexTypeu)
{
//用普里姆算法从第u个顶点出发构造网G的最小生成树T,输出T的各条边。
//记录从顶点集U到V-U的代价最小的边的辅助数组定义见"AdjacencyMatrix.h"
inti,j,k,totalCost=0;
closedgecloseEdge;
k=LocateVex(G,u);
for(j=0;j{
if(j!
=k)
{
strcpy(closeEdge[j].adjvex,u);
closeEdge[j].lowcost=G.arcs[k][j].adj;
}
}
cout<<"\n\n+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\\\n";
cout<<"|用Prim算法求最小生成树的各条边依次为:
\n-----";
closeEdge[k].lowcost=0;//初始,U={u};
for(i=1;i{
k=Minimum(closeEdge,G.vexnum);//求出T的下一个结点:
第k顶点
//此时closeEdge[k].lowcost=MIN{closeEdge[vi].lowcost|closeEdge[vi].lowcost>0,vi∈V-U}
cout<<'<'<';//输出生成树的边
totalCost+=closeEdge[k].lowcost;
closeEdge[k].lowcost=0;//第k顶点并入U集
for(j=0;j{
if(G.arcs[k][j].adj{
strcpy(closeEdge[j].adjvex,G.vexs[k]);
closeEdge[j].lowcost=G.arcs[k][j].adj;
}
}
}
cout<<"\n|总代价:
"<cout<<"+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^/\n";
}//MiniSpanTree
四、【实例测试及运行结果】
五、【心得体会】
通过本周的课程设计,我有不少收获。
既巩固和加深了对数据结构的理解,认识到《数据结构》是计算机专业一门重要的专业技术基础课程,还提高了我综合运用本课程所学知识的能力。
而且,并不是单纯的看看教材就能解决我们的实际问题,所以还要去查找各种我们所需要的资料,所以这次课程设计也培养了我选用参考书,查阅手册及文献资料的能力。
要完成一个课程设计的课题并不是一次就能编译成功的,中间会出现很多的大问题小问题,改错是个很繁琐的问题。
通过这次课程设计培养了我独立思考,深入研究,分析问题,解决问题的能力。
在以后的学习过程中我将要注意以下几点:
1、认真上好专业实验课,多在实践中锻炼自己。
2、写程序的过程要考虑周到,严密。
3、在做设计的时候要有信心,有耐心,切勿浮躁。
4、认真的学习课本知识,掌握课本中的知识点,并在此基础上学会灵活运用。
5、在课余时间里多写程序,熟练掌握在调试程序的过程中所遇到的常见错误,以便能节省调试程序的时间。
实验二:
统计数字
专业:
__软件工程___班级:
__软件_姓名:
_王____学号:
_20100034
完成日期:
_2010/6/28_______
1.【问题描述】
某次科研调查时得到了n个自然数,每个数均不超过1500000000(1.5*109)。
已知不相同的数不超过10000个,现在需要统计这些自然数各自出现的次数,并按照自然数从小到大的顺序输出统计结果。
2【设计需求及分析】
(1)设计要求
原始数据保存在文件count.in中,文件包含n+1行。
第1行是整数n(1<=n<=200000),表示自然数的个数;第2~n+1行每行一个自然数。
结果保存在文件count的尾部,其中结果包含m行(m为n个自然数中不相同数的个数),按照自然数从小到大的顺序输出。
每行输出两个整数,分别是自然数和该数出现的次数,其间用一个空格隔开。
(2)设计思路
首先必须有文件的打开和关闭语句,将文件的内容读取到数组a[]中,然后对数组进行排列和对比,计数。
最终输出数据和次数。
并写入文件的尾部。
A[]为容纳数据的数组,fopen为文件打开函数,fscanf为文件读取函数,然后进行冒泡排序。
排序之后的内容由while设置条件,用if进行判断。
在不等于时,中间嵌套了一个while循环,进行往后的排查。
最后输出数据和次数。
下面是关键步骤:
FILE*fp=fopen("count.txt","a+");//用只读/的方式打开文件
if(fp==NULL){
printf("无文件");//若没有文件则返回—1
return-1;}
for(i=0;i<9;i++){
fscanf(fp,"%d",&a[i]);//读取文件
fscanf(fp,"\n");}
intj,t;
for(i=1;i<9;i++)
for(j=0;j<9-i;j++)
if(a[j]>a[j+1]){//冒泡排序
t=a[j];
a[j]=a[j+1];
a[j+1]=t;
}
for(i=0;i<9;i++){
count=1;if(a[i]!
=a[i+1]){
printf("%d\t%d\n",a[i],count);
fprintf(fp,"%d\t%d\n",a[i],a[i]);
i++;
}对数字的循环查找和控制条件,if(a[i]==a[i+1])
{
while(a[i]==a[i+1])
{
count++;
i++;}
}
}
(3)输出输入格式
输入时,为竖行依此输入文件,且为数字。
且为9个以内的数字。
输出时,分为两行,第一列为数据,第二列为次数。
3.【设计功能的实现】
#includeintmain(){
inta[100];//创建容纳文件数据的数组inti;
FILE*fp=fopen("count.txt","a+");//用只读/的方式打开文件if(fp==NULL){
printf("无文件");//若没有文件则返回—1return-1;}
for(i=0;i<9;i++){
fscanf(fp,"%d",&a[i]);//读取文件fscanf(fp,"\n");}
intj,t;
for(i=1;i<9;i++)
for(j=0;j<9-i;j++)
if(a[j]>a[j+1])
{//冒泡排序
t=a[j];
a[j]=a[j+1];
a[j+1]=t;}
printf("结果为:
\n数据结果\n");intcount;
for(i=0;i<9;i++){
count=1;if(a[i]!
=a[i+1]){
printf("%d\t%d\n",a[i],count);
printf(fp,"%d\t%d\n",a[i],a[i]);
i++;
}
if(a[i]==a[i+1])
{
while(a[i]==a[i+1])
{
count++;
i++;
}
printf("%d\t%d\n",a[i],count);
fprintf(fp,"%d\t%d\n",a[i],count);
}
}
fclose(fp);//关闭文件
return0;
}
4.【实例测试及运行结果】
5.【心得体会】
本次实验使我对于文件的打开和关闭语句有了更深的理解。
有打开必须有关闭。
同时在这次的设计中,我学习到了用泛洪算法解决实际问题的基本思维和步骤。
使我对算法的层次性更加清楚,更加加深了对算法的理解。
实验三.送货
专业:
__软件工程___班级:
__软件姓名:
_王_学号:
_20100034
完成日期:
_2010/6/26________
1.【问题描述】
小明希望设计一个方案,从编号为1的交叉路口出发,每次必须沿街道去往街道另一端的路口,再从新的路口出发去往下一个路口,直到所有的街道都