管道铺设课程设计报告.docx
《管道铺设课程设计报告.docx》由会员分享,可在线阅读,更多相关《管道铺设课程设计报告.docx(20页珍藏版)》请在冰豆网上搜索。
管道铺设课程设计报告
编号:
理工大学
数据结构课程设计报告
班级:
学号:
姓名:
时间:
2015年6月22日
~2015年7月3日
指导教师:
2015年06月
一、摘要.....................................................................3
二、引言.......................................................................3
三、需求分析...............................................................3
四、概要设计...............................................................4
1.普利姆算法分析...............................................6
2.模块分析...........................................................6
3.抽象数据类型分析...........................................6
4.全部流程...........................................................6
五、详细设计...............................................................7
1.算法分析...........................................................7
(一)信息输入模块.........................................7
(二)建立最小生成树并输出结果.................8
2.源程序代码.......................................................9
六、测试结果...............................................................14
程序开始...............................................................14
信息输入...............................................................14
输出结果...............................................................14
七、设计体会...............................................................15
八、结束语...................................................................16
参考文献...............................................................16
一、摘要
N(N>10)个居民区之间需要铺设煤气管道。
假设任意两个居民区之间都可以铺设煤气管道,但代价不同。
问题的实质就是编写相应程序求解最小生成树问题。
程序要求:
事先任意两个居民区之间铺设煤气管道的代价存入磁盘文件中。
设计一个最佳方案使得这N个居民区之间铺设煤气管道所需代价最小,并将结果以图形方式在屏幕上输出。
二、引言
C语言作为一门最通用的语言,从语言产生到现在,它已经成为最重要和最流行的编程语言之一。
在各种流行编程语言中,都能看到C语言的影子。
学习掌握C语言是每一个计算机技术人员的基本功之一。
实际生活中最小生成树的问题具有很大的意义。
例如,本文所讨论的构架居民区之间铺设煤气管道代价最小,还有在若干地区铺设光缆等等。
最小生成树让许多诸如求造价最小、最短路径等最优化的现实问题找到了理论依据,并提供了有效的解决方法。
三需求分析
在N(N>10)个居民区之间铺设煤气管道所需代价最小,即求最小生成树问题。
在我们的课本中介绍了两种求解方法:
普利姆算法和克鲁斯卡尔算法。
普利姆算法与网的变数无关,适宜求解边稠密的网的最小生成树。
而克鲁斯卡尔算好相反,
适宜求解边稀疏的最小生成树。
由于在实际问题中,居民数量一般很有限,而任何两个居民区都可能有连线,即这样的图应该是边较为稠密的。
因此,我们选择了普利姆算法对问题进行求解。
四概要设计
1.普利姆算法分析
1普利姆算法思想
普利姆算法的思想是:
在图中人去一个定点k0作为开始点,令U={k0},W=V-U,
其中V为图中所有顶点集,然后找一个顶点在U中,另一个顶点在w中的边中最短
的一条,找到后,将该边作为最小生成树的树边保存起来,并将该边顶点全部加入U集合中,并从W中删除这些顶点,然后重新调整U中顶点到W中顶点的距离,使之保持最小,再重复此过程,直到W为空集。
2算法过程描述
1)在图G=(V,E)(V是顶点,E是边)中,从集合V中任取一个顶点,如k0放入集合U中,这时,U={k0},集合T(E)为空。
2)从k0出发寻找与U中顶点相邻权值最小的边的另一顶点k1,并使k1加入U。
即U={k0,k1},同时将该边加入集合T(E)中。
3)重复
(2),直到U=V为止。
4)这时T(E)中有n-1条边,T=(U,T(E))就是一一颗最小生成树。
2、模块分析
根据对模型的功能分析,该管道铺设设计可以具有以下功能:
1管道铺设信息的输入;
2最小生成树信息的输出;
功能模块图:
3.抽象数据类型分析
areanum居民区总数(顶点总数);
edgenum边的总数;
date[][20]邻接矩阵存储图结构;
s边的权值;
short-way[i]居民区i到目前生成树中所有点集U中某个居民区的路程最小值
near-area[i]U中能使其最小的居民区
5.全部流程
五、详细设计
1.算法分析
1信息输入模块
//读入图的信息,并将邻接矩阵输出
Voidread()
{//输入顶点个数和边的条数
Printf(“请输入:
定点数,变数:
\n”);
Scanf(“%d,%d”,&areanum,&dedgenm);
//初始化邻接矩阵各元素值
Inti,j,k;
for(i=0;ifor(j=0;jdate[i][j]=INFINITY;
//读入边
Intfrom,to,s;
Printf(“输入边,格式为i,j,k,表示i到j的权值是k:
\n”);
For(i=0;i{
Scanf(“%d,%d,%d”,&from,&to,&s);
date[from][to]=s;
date[to][from]st;
}
//输出邻接矩阵
for(i=0;i{
for(j=0;jPrintf(“%d\t”,date[i][j]);
Printf(“\n”);
}
}
2建立最小生成树并输出结果
//用普里姆算法从第u个顶点出发构造网G的最小生成树T,输出T的各条边
voidMiniSpanTree_PRIM(MGraphG,VertexTypeu)
{//system("cls");
inti,j,k;
minsideclosedge;
k=LocateVex(G,u);
for(j=0;j{
if(j!
=k)
{
strcpy(closedge[j].adjvex,u);
closedge[j].lowcost=G.arcs[k][j].adj;
}
}
closedge[k].lowcost=0;//初始,U={u}
printf("最小代价生成树的各条边为:
\n");
for(i=1;i{//选择其余G.vexnum-1个顶点
k=minimum(closedge,G);//求出T的下一个结点:
第K顶点
printf("(%s-%s)\n",closedge[k].adjvex,G.vexs[k]);//输出生成树的边
closedge[k].lowcost=0;//第K顶点并入U集
for(j=0;jif(G.arcs[k][j].adj{
//新顶点并入U集后重新选择最小边
strcpy(closedge[j].adjvex,G.vexs[k]);
closedge[j].lowcost=G.arcs[k][j].adj;
}
}
system("pause");
}
2.源程序代码
#include
#include
#include
#include
#include
#defineMAX_VERTEX_NUM20//最大顶点个数
#defineMAX_NAME3//顶点字符串的最大长度+1
//#defineMAX_INFO20//相关信息字符串的最大长度+1
#defineINFINITYINT_MAX//用整型最大值代替∞
typedefintVRType;
typedefcharInfoType;
typedefcharVertexType[MAX_NAME];
//邻接矩阵的数据结构
typedefstruct
{
VRTypeadj;//顶点关系类型。
对无权图,用1(是)或0(否)表示相邻否;
//对带权图,则为权值类型
InfoType*info;//该弧相关信息的指针(可无)
}ArcCell,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
//图的数据结构
typedefstruct
{
VertexTypevexs[MAX_VERTEX_NUM];//顶点向量
AdjMatrixarcs;//邻接矩阵
intvexnum,//图的当前顶点数
arcnum;//图的当前弧数
}MGraph;
//记录从顶点集U到V-U的代价最小的边的辅助数组定义
typedefstruct
{
VertexTypeadjvex;
VRTypelowcost;
}minside[MAX_VERTEX_NUM];
//若G中存在顶点u,则返回该顶点在图中位置;否则返回-1。
intLocateVex(MGraphG,VertexTypeu)
{
inti;
for(i=0;iif(strcmp(u,G.vexs[i])==0)
returni;
return-1;
}
//代价保存为文件
//代价存入文件
voidwenjian()
{
//system("cls");
FILE*fp;
chars[50],ch;
strcpy(s,"D:
\\record.txt");
if((fp=fopen(s,"ab+"))==NULL)
{
printf("无法打开此文件\n");
exit(0);
}
else
{
//printf("请向磁盘中输入原点总数和边的总数:
\n");
//printf("请输入顶点数边数\n");
//scanf("%d%d",&G.vexnum,&G.arcnum);
//printf("请输入各居民点:
");
//for(inti=1;i<=N;i++)
//{
//scanf("%c",&G.vexs[i]);
//}in
//fput(G.vexs[i],fp);
//}
//printf("请向磁盘中输入各原点和边的总数同时记录原点,目的点,及相应的权值:
(输入#键表示结束)\n");
printf("请向磁盘中输入各原点和边的总数:
(输入$键表示结束)\n");
ch=getchar();
while(ch!
='$')
{
fputc(ch,fp);
ch=getchar();
}
printf("请向磁盘中输入原点,目的点,及相应的权值:
(输入#键表示结束)\n");
ch=getchar();
while(ch!
='#')
{
fputc(ch,fp);
ch=getchar();
}
}
fclose(fp);
system("pause");
}
//从文件中得到信息构成图
voidxianshi()
{
//system("cls");
FILE*fp;
chars[50],ch;
strcpy(s,"D:
\\record.txt");
if((fp=fopen(s,"r"))==NULL)
{
printf("无法打开此文件\n");
exit(0);
}
else
{
while(!
feof(fp))
{
ch=fgetc(fp);
putchar(ch);
}
}
putchar(10);
fclose(fp);
system("pause");
}
//算法7.2P162
//采用数组(邻接矩阵)表示法,构造无向网G。
intCreateAN(MGraph*G)
{
//system("cls");
inti,j,k,w;
//chars[MAX_INFO],*info;
//char*info;
VertexTypeva,vb;
printf("请输入无向网G的顶点数,边数,(空格区分)");
scanf("%d%d",&(*G).vexnum,&(*G).arcnum);
printf("请输入%d个顶点的值:
\n",(*G).vexnum);
for(i=0;i<(*G).vexnum;++i)//构造顶点向量
scanf("%s",(*G).vexs[i]);
for(i=0;i<(*G).vexnum;++i)//初始化邻接矩阵
for(j=0;j<(*G).vexnum;++j)
{
(*G).arcs[i][j].adj=INFINITY;//网初始化为无穷大
//(*G).arcs[i][j].info=NULL;
}
printf("请输入%d条边的顶点1顶点2权值(以空格作为间隔):
\n",(*G).arcnum);
for(k=0;k<(*G).arcnum;++k)
{
scanf("%s%s%d%*c",va,vb,&w);//%*c吃掉回车符
i=LocateVex(*G,va);
j=LocateVex(*G,vb);
(*G).arcs[i][j].adj=(*G).arcs[j][i].adj=w;//无向
//if(IncInfo)
//{
//printf("请输入该边的相关信息(<%d个字符):
",MAX_INFO);
//gets(s);
//w=strlen(s);
//if(w)
//{
//info=(char*)malloc((w+1)*sizeof(char));
//strcpy(info,s);
//(*G).arcs[i][j].info=(*G).arcs[j][i].info=info;//无向
//}
//}
}
printf("输出临接矩阵:
\n");
for(i=0;i<(*G).vexnum;++i)
for(j=0;j<(*G).vexnum;++j)
{if(j%3==0)printf("\n");
printf("%d",(*G).arcs[i][j].adj);
}
return1;
system("pause");
}
//求closedge.lowcost的最小正值
intminimum(minsideSZ,MGraphG)
{
inti=0,j,k,min;
while(!
SZ[i].lowcost)
i++;
min=SZ[i].lowcost;//第一个不为0的值
k=i;
for(j=i+1;jif(SZ[j].lowcost>0)
if(min>SZ[j].lowcost)
{
min=SZ[j].lowcost;
k=j;
}
returnk;
}
//算法7.9P175
//用普里姆算法从第u个顶点出发构造网G的最小生成树T,输出T的各条边
voidMiniSpanTree_PRIM(MGraphG,VertexTypeu)
{//system("cls");
inti,j,k;
minsideclosedge;
k=LocateVex(G,u);
for(j=0;j{
if(j!
=k)
{
strcpy(closedge[j].adjvex,u);
closedge[j].lowcost=G.arcs[k][j].adj;
}
}
closedge[k].lowcost=0;//初始,U={u}
printf("最小代价生成树的各条边为:
\n");
for(i=1;i{//选择其余G.vexnum-1个顶点
k=minimum(closedge,G);//求出T的下一个结点:
第K顶点
printf("(%s-%s)\n",closedge[k].adjvex,G.vexs[k]);//输出生成树的边
closedge[k].lowcost=0;//第K顶点并入U集
for(j=0;jif(G.arcs[k][j].adj{
//新顶点并入U集后重新选择最小边
strcpy(closedge[j].adjvex,G.vexs[k]);
closedge[j].lowcost=G.arcs[k][j].adj;
}
}
system("pause");
}
voidmain()
{//system("cls");
MGraphG;
intxz;
while
(1)
{
//system("cls");
printf("\n");
printf("*******************************管道铺设最佳方案选择*******************\n");
printf("0记录保存为文件\n");
printf("1从文件中读记录\n");
printf("2构造无向网\n");
printf("3求出最小生成树\n");
printf("4退出\n");
printf("**********************************************************************\n");
printf("请输入操作序号(0-4):
\n");
scanf("%d",&xz);
switch(xz)
{
case0:
wenjian();break;
case1:
xianshi();break;
case2:
CreateAN(&G);break;
case3:
MiniSpanTree_PRIM(G,G.vexs[0]);break;
case4:
exit(0);
default:
printf("输入无效指令!
按任意键继续!
");
system("pause");
}
}
//system("pause");
}
六.测试结果
七.设计体会
通过数据结构的课程设计使我们对所学知识有了更好的理解,也增强了大家的动手能力。
同时也发现了自己的很多不足之处,对知识的应用能力很是欠缺,应用软件的能力及编程水平与课程要求更是存在很大的差距。
程序的运行结果与理论推导结果完全吻合,即该算法与程序设计满足课程设计要求。
该程序的主要优点是简单易懂,不存在理解上的障碍,也很自然地能想到这种解法。
主要缺点是程序的变动性比较差—初始化邻接矩阵后结果就固定了。
如果能加入图行和图的修改、插入、删除等操作,我想应该会好很多。
八、结束语
转眼,为期两周的《数据结构》课程设计即将结束了。
在这次课程设计中我的c语言知识和数据结构知识得到了很好学习。
编程能力也有了一定的提高。
同时也学回了解决问题的方法。
总结起来,自己主要有以下几点体会:
1.必须牢固掌握基础知识。
由于C语言是大一所学知识,没有好好的去体会掌握,同时也没有掌握好上学期学的《数据结构》这门课,所以在课程设计初期感到无从下手,但在后来的设计过程中自己通过看书和课外资料,并请教其他同学,慢慢地对C语言和数据结构知识有所了解和熟悉。
这时才逐渐有了思路。
所以,在这次课程设计以后,我下了决心:
以后一定要好好学习好专业知识。
2.必须培养严谨的科学态度。
我在编写程序时经常因为一些类似于少写了分号,大括号不匹配等造成的程序调试失败,不够认真仔细,给自己带来了许多麻烦。
3.这次课程设计也让我充分的认识到《数据结构》这门课的重要性。
它给我们的一个思想和大纲,让我们再编程时更容易找到思路,不至于无章可循。
同时它也有更广泛的实际应用价值。