基于Floyd算法的最短路径问题的求解c++Word格式文档下载.docx
《基于Floyd算法的最短路径问题的求解c++Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《基于Floyd算法的最短路径问题的求解c++Word格式文档下载.docx(21页珍藏版)》请在冰豆网上搜索。
由此所得广度优先生成树上,从根顶点A到顶点B的路径就是中转次数最少的路径,路径上A与B之间的顶点就是途径中的中转站数。
但是这只是一类最简单的图的最短路径的问题。
有时对于旅客来说,可能更关心的是节省交通费用;
对于司机来说里程和速度则是他们感兴趣的信息。
为了在图上标示有关信息可对边赋以权的值,权的值表示两城市间的距离,或图中所需时间,或交通费用等等。
此时路径长度的量度就不再是路径上边的数目,而是路径上边的权值之和。
边赋以权值之后再结合最短路径算法来解决这些实际问题。
Floyd算法是最短路径经典算法中形式较为简单,便于理解的一种。
2算法基本原理
2.1邻接矩阵
邻接矩阵(AdjacencyMatrix):
是表示顶点之间相邻关系的矩阵。
设G=(V,E)是一个图,其中V={v1,v2,…,vn}。
G的邻接矩阵是一个具有下列性质的n阶方阵:
(1)对无向图而言,邻接矩阵一定是对称的,而且对角线一定为零(在此仅讨论无向简单图),有向图则不一定如此。
(2)在无向图中,任一顶点i的度为第i列所有元素的和,在有向图中顶点i的出度为第i行所有元素的和,而入度为第i列所有元素的和。
(3)用邻接矩阵法表示图共需要个空间,由于无向图的邻接矩阵一定具有对称关系,所以扣除对角线为零外,仅需要存储上三角形或下三角形的数据即可,因此仅需要n/2个空间。
2.2弗洛伊德算法
弗洛伊德算法使用图的邻接矩阵arcs[n+1][n+1]来存储带权有向图。
算法的基本思想是:
设置一个nxn的矩阵A(k),其中除对角线的元素都等于0外,其它元素a(k)[i][j]表示顶点i到顶点j的路径长度,K表示运算步骤。
开始时,以任意两个顶点之间的有向边的权值作为路径长度,没有有向边时,路径长度为∞,当K=0时,A(0)[i][j]=arcs[i][j],以后逐步尝试在原路径中加入其它顶点作为中间顶点,如果增加中间顶点后,得到的路径比原来的路径长度减少了,则以此新路径代替原路径,修改矩阵元素。
具体做法为:
第一步,让所有边上加入中间顶点1,取A[i][j]与A[i][1]+A[1][j]中较小的值作A[i][j]的值,完成后得到A
(1);
第二步,让所有边上加入中间顶点2,取A[i][j]与A[i][2]+A[2][j]中较小的值,完成后得到A
(2)…,如此进行下去,当第n步完成后,得到A(n),A(n)即为我们所求结果,A(n)[i][j]表示顶点i到顶点j的最短距离。
因此弗洛伊德算法可以描述为:
A(0)[i][j]=arcs[i][j];
//arcs为图的邻接矩阵
A(k)[i][j]=min{A(k-1)[i][j],A(k-1)[i][k]+A(k-1)[k][j]},其中k=1,2,…,n
(1)
定义一个n阶方阵序列:
D(-1),D(0),…,D(n-1).
D(-1)[i][j]=G.arcs[i][j];
D(k)[i][j]=min{D(k-1)[i][j],D(k-1)[i][k]+D(k-1)[k][j]},k=0,1,…,n-1
(2)
其中D(0)[i][j]是从顶点vi到vj中间顶点是v0的最短路径的长度;
D(k)[i][j]是从顶点vi到vj中间顶点的序号不大于k的最短路径长度;
D(n-1)[i][j]是从顶点vi到vj的最短路径长度。
3类设计
3.1类的概述
类代表了某一批对象的共性和特征。
类是对象的抽象。
类这种数据类型中的数据既包含数据也包含操作数据的函数。
声明类的一般形式:
class类名
{private:
私有的数据和成员函数;
public:
公用的数据和成员函数;
};
定义对象:
类名对象名;
可以在类外定义成员函数,在函数名前加上类名,“:
:
”是作用域限定符或称作用域运算符用它说明函数式属于哪个类的。
如下面程序中的
voidMGraph:
:
CreateMGraph(MGraph&
G)
{
函数体
}
3.2类的接口设计
#include<
iostream>
#include<
string>
stdio.h>
usingnamespacestd;
#defineMaxVertexNum100
#defineINF32767
classMGraph
{private:
charvertex[MaxVertexNum];
//顶点信息
intedges[MaxVertexNum][MaxVertexNum];
//邻接矩阵
intn,e;
//顶点数和边数
voidCreateMGraph(MGraph&
);
//构造有向图
voidPpath(int[][100],int,int);
voidDispath(int[][100],int[][100],int);
//输出最短路径
voidFloyd(MGraphG);
//Floyd算法的具体实现
};
首先将所需文件名写好,定义类MGraph。
在进行类体构造时将数据charvertex[MaxVertexNum]、intedges[MaxVertexNum][MaxVertexNum]和intn,e定义为私有数据,将成员函数voidCreateMGraph(MGraph&
)、voidPpath(int[][100],int,int)、voidDispath(int[][100],int[][100],int)和voidFloyd(MGraphG)定义为公用的,以便非类体内的数据调用函数。
3.3类的实现
G)//构造有向图
{
inti,j,k,p;
cout<
<
"
请输入顶点数和边数:
;
cin>
>
G.n>
G.e;
请输入顶点元素:
for(i=0;
i<
G.n;
i++)
{
G.vertex[i];
}
for(j=0;
j<
j++)
G.edges[i][j]=INF;
if(i==j)
G.edges[i][j]=0;
for(k=0;
k<
k++)
请输入第"
k+1<
条弧头弧尾序号和相应的权值:
i>
j>
p;
G.edges[i][j]=p;
Ppath(intpath[][MaxVertexNum],inti,intj)//Ppath()函数在path中递归输出从顶点vi到vj的最短路径。
intk;
k=path[i][j];
if(k==-1)//path[i][j]=i时,顶点vi和vj之间无中间顶点,也就是说找到了始节点
return;
Ppath(path,i,k);
printf("
%d"
k);
Ppath(path,k,j);
}
Dispath(intA[][MaxVertexNum],intpath[][MaxVertexNum],intn)//输出最短路径的算法
inti,j;
n;
if(A[i][j]==INF)
if(i!
=j)
从%d到%d没有路径\n"
i,j);
else
从%d到%d=>
路径长度:
%d路径:
i,j,A[i][j]);
%d,"
i);
Ppath(path,i,j);
%d\n"
j);
Floyd(MGraphG)
intA[MaxVertexNum][MaxVertexNum],path[MaxVertexNum][MaxVertexNum];
inti,j,k;
A[i][j]=G.edges[i][j];
path[i][j]=-1;
k++)///向vi与vj之间中n次加入中间顶点
if(A[i][j]>
A[i][k]+A[k][j])
A[i][j]=A[i][k]+A[k][j];
path[i][j]=k;
//表示从i节点到j节点,要经过k节点
Dispath(A,path,G.n);
4基于控制台的应用程序
4.1主函数设计
intmain()
MGraphG;
G.CreateMGraph(G);
G.Floyd(G);
return0;
在程序的主函数部分,定义一个MGrapha类的对象G,调用成员函数CreateMGraph()和Floyd()分别完成了采用图的邻接矩阵实现最短路径问题中图的存储和采用Floyd算法求每一对顶点的最短路径的任务。
4.2运行结果及分析
将待测图的相关数据输入则得到如图1的运行结果。
图1程序运行结果
从图1可以看出:
整个程序中的矩阵存储采用的是一维数组和动态内存分配方式。
通过此类定义邻接矩阵,采用图的邻接矩阵实现最短路径问题中图的存储,然后通过主函数main调用class来实现,采用Floyd算法求每对顶点间最短路径从某个源点到其余各顶点的最短路径。
将图的基本信息输入,顶点数和边数4、8,顶点元素A、B、C、D,8条弧各自的序号和权值。
运行程序得出每对顶点间的最短路径长度和路径。
基于Floyd算法成功的解决了最短路径问题。
5基于MFC的应用程序
MFC的图形界面程序与DOS界面程序的主要不同点是:
MFC图形界面程序与DOS界面程序的输