论文之图的建立与最短路径.docx
《论文之图的建立与最短路径.docx》由会员分享,可在线阅读,更多相关《论文之图的建立与最短路径.docx(10页珍藏版)》请在冰豆网上搜索。
![论文之图的建立与最短路径.docx](https://file1.bdocx.com/fileroot1/2022-12/16/7ee53f7b-7683-445a-9fba-32b4c530e12a/7ee53f7b-7683-445a-9fba-32b4c530e12a1.gif)
论文之图的建立与最短路径
图的建立与最短路径
学生姓名:
xxx指导老师:
xxx
摘要本课程主要是设计一个算法程序以建立一个图并求其最短路径,其具体要求如下:
以邻接矩阵的形式确定一个图,建立并显示它的邻接链表,给出某一确定顶点到所有其它顶点的最短路径。
在课程设计中,系统开发平台为Windows7,程序设计语言采用VisualC++,程序运行平台为Windows7。
为了求出某一确定顶点到所有其它顶点的最短路径,我采用了迪杰斯特拉(Dijkstra)算法思想----按路径长度递增的次序产生最短路径。
通过本次课程设计以最终达到能在实际生活中应用为目的。
关键词数据结构;图;Dijkstra算法;最短路径
目录
1引言……………………………………………………………1
1.1课程设计目的……………………………………………1
1.2课程设计内容……………………………………………1
2设计思路与方案………………………………………………2
3详细实现………………………………………………………4
4运行环境与结果………………………………………………8
5结束语…………………………………………………………9
参考文献…………………………………………………………10
附录源程序代码………………………………………………11
1引言
1.1课程设计目的
“数据结构”在计算机科学中是一门综合性的专业基础课。
“数据结构”的研究不仅涉及到计算机硬件(特别是编码理论、存储装置和存取方法等)的研究范围,而且和计算机软件的研究有着更密切的关系,无论是编译程序还是操作系统,都涉及到数据元素在存储器中的分配问题。
在研究信息检索时也必须考虑如何组织数据,以便查找和存取数据元素更为方便。
因此,可以认为“数据结构”是介于数学、计算机硬件和计算机软件三者之间的一门核心课程。
在计算机科学中,“数据结构”不仅是一般程序设计(特别是非数学计算的程序设计)的基础,而且是设计和实现编译程序、操作系统、数据库系统及其它系统程序和大型应用程序的重要基础。
由此可见,“数据结构”的学习对我们专业的学生来说非常重要,通过这次数据结构课程设计,相信最终能让我们学以致用,更好的理解并掌握数据结构这门课程中所介绍的方法思想。
1.2课程设计内容
以邻接矩阵的方式确定一个图,完成:
⑴建立并显示出它的邻接链表;
⑵给出某一确定顶点到所有其它顶点的最短路
2设计思路与方案
图是一种较线性表和树更为复杂的数据结构[1]。
在线性表中,数据元素之间仅有线性关系,每个数据元素只有一个直接前驱和一个直接后继;在树形结构中,数据元素之间有着明显的层次关系,并且每一层上的数据元素可能和下一层中多个元素(即其孩子节点)相关,但只能和上一层中一个元素(即其双亲节点)相关;而在图形结构中,节点之间的关系可以是任意的,图中任意两个数据元素之间都可能相关。
图的结构比较复杂,任意两个顶点之间都可能存在联系,因此无法以数据元素在存储区中的物理位置来表示元素之间的关系,即图没有顺序映像的存储结构,但可以借助数组的数据类型表示元素之间的关系。
另一方面,用多重链表表示图是自然的事,它是一种最简单的链式映像结构,即以一个由一个数据域和多个指针域组成的结点表示图中的一个顶点,其中数据域存储该顶点的信息,指针域存储指向其邻接点的指针。
但是由于图中各个结点的度数各不相同,最大度数和最小度数可能相差很多,因此,若按度数最大的顶点设计结点结构,则会浪费很多存储单元;反之,若按每个顶点自己的度数设计不同的结点结构,又会给操作带来不便。
因此,和树类似,在实际应用中不宜采用这种结构,而应根据具体的图和需要进行的操作,设计恰当的结点结构和表结构。
而如何求图中某个源点到其余各顶点的最短路径?
迪杰斯特拉(Dijkstra)提出了一个按路径长度递增的次序产生最短路径的算法[3]。
而在该设计中,我正是采用了这种算法思想。
首先,引用一个辅助向量D,它的每个分量D[i]表示当前所找到的从始点v到每个终点vi的最短路径的长度。
它的初态为:
若从v到vi有弧,则D[i]为弧上的权值;否则置D[i]为∞。
显然长度为
D[j]=Min{D[i]|vi∈V}
的路径就是从v出发的长度最短的一条最短路径。
此路径为(v,vj)。
那么,下一条长度次短的最短路径是哪一条呢?
假设该次短路径的终点是vk,则可想而知,这条路径或者是(v,vk),或者是(v,vj,vk).它的长度或者是从v到vk的弧上的权值,或者是D[j]和从vj到vk的弧上的权值之和。
一般情况下,假设S为已求得最短路径的终点的集合,则可证明:
下一条最短路径(设其终点为x)或者是弧(v,x),或者是中间只经过S中顶点而最后到达顶点x的路径。
这可用反证法来证明。
假设此路径上有一个顶点不在S中,则说明存在一条终点不在S而长度比此路径短的路径。
但是,这是不可能的。
因为我们是按路径长度递增的次序来产生各最短路径的,故长度比此路径短的所有路径均已产生,它们的终点必定在S中,则假设不成立。
因此,在一般情况下,下一条长度次短的最短路径的长度必是
D[j]=Min{D[i]|vi∈V-S}
其中,D[i]或是弧(v,vi)上的权值[2],或者是D[k](vk∈S)和弧(vk,vi)上的权值之和。
3详细实现
首先,我创建了一个主函数main,在该主函数中,首先调用CreateD函数,创建一个图,然后要求用户输入始点,接着调用求最短路径的ShortestPath_DIJ函数,就可输出该始点到其它各个顶点的最短路径了。
其主函数main具体算法如下:
intmain(){
MGraphG;
CreateD(G);
intv0;
printf("请输入始点:
");
scanf("%d",&v0);
ShortestPath_DIJ(G,v0-1);
for(inti=0;iif(i!
=v0-1){
printf("V%dtoV%dis:
",v0,i+1);
printf("<");
for(intj=0;jif(P[i][j]&&j!
=i)
printf("V%d,",j+1);
printf("V%d>",i+1);
printf("--Lengthis:
%d\n",D[i]);
}
}
return0;
}
创建图的函数CreateD具体算法如下:
boolCreateD(MGraph&G){
intIncInfo,v1,v2,w,i,j,k;
printf("请输入有向图的顶点数和弧数,以及各弧是否含有其他信息(0表示不含其它信息)\n");
scanf("%d%d%d",&G.vexnum,&G.arcnum,&IncInfo);
for(i=0;iG.vexs[i]=i+1;
for(i=0;ifor(j=0;jG.arcs[i][j].adj=INFINITY;G.arcs[i][j].info=NULL;
}
}
for(k=0;kprintf("请输入第%d弧的两个节点及权值:
",k+1);
scanf("%d%d%d",&v1,&v2,&w);
i=LocateVex(G.vexs,v1);j=LocateVex(G.vexs,v2);//找到两个顶点在邻接矩阵中的位置
G.arcs[i][j].adj=w;
if(IncInfo)
scanf("%s",G.arcs[i][j].info);//若弧含有相关信息,则输入信息
}
returntrue;
}
根据迪杰斯特拉思想,我们可以得到如下的求取图的最短路径的描述算法:
(1)假设用带权的邻接矩阵arcs来表示带权有向图,arcs[i][j]表示弧上的权值。
若不存在,则置arcs[i][j]为∞(在计算机上可用允许的最大值代替)。
S为已找到从v出发的最短路径的终点的集合,它的初始状态为空集。
那么,从v出发到图上其余各顶点(终点)vi可能达到的最短路径长度的初值为:
D[i]=arcs[LocateVex(G,v)[i]vi∈V
(2)选择vj,使得
D[j]=Min{D[i]|vi∈V-S}
Vj就是当前求得的一条从v出发的最短路径的终点。
令
S=S∪{j}
(3)修改从v出发到集合V-S上任一顶点vk可达的最短路径长度。
如果D[j]+arcs[j][k]则修改D[k]为
D[k]=D[j]+arcs[j][k]
(4)重复操作
(2)、(3)共n-1次。
由此求得从v到图上其余各顶点的最短路径是依路径长度递增的序列。
以下为具体的算法:
voidShortestPath_DIJ(MGraphG,intv0){
inti,w,v;
for(v=0;vD[v]=G.arcs[v0][v].adj;
for(w=0;wP[v][w]=false;
if(D[v]P[v][v0]=true;P[v][v]=true;
}
}
D[v0]=0;final[v0]=true;
for(i=1;iintmin=MAX_SIZE;
for(w=0;wif(!
final[w])
if(D[w]min=D[w];v=w;
}
final[v]=true;
for(w=0;wif(!
final[w]&&(min+G.arcs[v][w].adjD[w]=min+G.arcs[v][w].adj;
for(i=0;iP[w][i]=P[v][i];
P[w][w]=true;
}
}
}
4运行环境与结果
系统开发平台为Windows7,程序设计语言采用VisualC++,程序运行平台为Windows7。
写完程序后,就是运行程序并进行测试与改进了。
首先,运行后我们看到了一行提示项:
请输入有向图的顶点数和弧数,以及各弧是否含有其他信息(0表示不含其它信息)。
如下图4.1所示:
图4.1开始项
按提示输入相应数据,回车得到图的最短路径,如下图4.2所示:
图4.2最短路径
5结束语
“数据结构”是一门专业技术基础课,它的教学要求是:
学会分析研究计算机加工的数据结构的特性,以便为应用涉及的数据选择适当的逻辑结构、存储结构及相应的算法,并初步掌握算法的时间分析和空间分析的技术。
该课程的学习过程同时也是一个复杂程序设计的过程,要求学生编写的程序结构清楚和正确易读,符合软件工程的规范。
通过这次数据结构的课程设计,我对了上学期学习的“数据结构”的知识又有了一番新的理解,同时也锻炼了自己的编写能力和逻辑思维能力。
作为一名网络工程专业的学生,我觉得我们就该如此,应不断写程序,最终把书本上的东西学以致用。
参考文献
[1]严蔚敏,吴伟民.数据结构(C语言版).北京:
清华大学出版社,1997,4.
[2]殷人昆.数据结构(用面向对象方法C++描述).清华大学出版社,2002,9.
[3]谭浩强.C语言程序设计教程.北京邮电大学出版社,2005,7
附录源程序代码
#include
#include
#include
#defineINFINITY0
#defineMAX_VERTEX_NUM20
#defineMAX_SIZE10000
typedefenum{DG,DN,UDG,UDN}GraphKind;
typedefstructArcCell{
intadj;
char*info;
}ArcCell,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
typedefstruct{
intvexs[MAX_VERTEX_NUM];
AdjMatrixarcs;
intvexnum,arcnum;
GraphKindkind;
}MGraph;
//-------
intLocateVex(intvexs[],intv){//确定节点v在节点向量中的位置
for(inti=0;iif(vexs[i]==v)
returni;
printf("不存在这个节点!
");
exit(0);
}
boolCreateD(MGraph&G){
intIncInfo,v1,v2,w,i,j,k;
printf("请输入有向图的顶点数和弧数,以及各弧是否含有其他信息(0表示不含其它信息)\n");
scanf("%d%d%d",&G.vexnum,&G.arcnum,&IncInfo);
for(i=0;iG.vexs[i]=i+1;
for(i=0;ifor(j=0;jG.arcs[i][j].adj=INFINITY;G.arcs[i][j].info=NULL;
}
}
for(k=0;kprintf("请输入第%d弧的两个节点及权值:
",k+1);
scanf("%d%d%d",&v1,&v2,&w);
i=LocateVex(G.vexs,v1);j=LocateVex(G.vexs,v2);//找到两个顶点在邻接矩阵中的位置
G.arcs[i][j].adj=w;
if(IncInfo)
scanf("%s",G.arcs[i][j].info);//若弧含有相关信息,则输入信息
}
returntrue;
}
//---------------------------------------------------
boolfinal[MAX_VERTEX_NUM]={false};//用于标记到顶点i的最短路径是否已经找到
boolP[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
intD[MAX_VERTEX_NUM]={0};
voidShortestPath_DIJ(MGraphG,intv0){
inti,w,v;
for(v=0;vD[v]=G.arcs[v0][v].adj;
for(w=0;wP[v][w]=false;
if(D[v]P[v][v0]=true;P[v][v]=true;
}
}
D[v0]=0;final[v0]=true;
for(i=1;iintmin=MAX_SIZE;
for(w=0;wif(!
final[w])
if(D[w]min=D[w];v=w;
}
final[v]=true;
for(w=0;wif(!
final[w]&&(min+G.arcs[v][w].adjD[w]=min+G.arcs[v][w].adj;
for(i=0;iP[w][i]=P[v][i];
P[w][w]=true;
}
}
}
intmain(){
MGraphG;
CreateD(G);
intv0;
printf("请输入始点:
");
scanf("%d",&v0);
ShortestPath_DIJ(G,v0-1);
for(inti=0;iif(i!
=v0-1){
printf("V%dtoV%dis:
",v0,i+1);
printf("<");
for(intj=0;jif(P[i][j]&&j!
=i)
printf("V%d,",j+1);
printf("V%d>",i+1);
printf("--Lengthis:
%d\n",D[i]);
}
}
return0;
}