当前位置:文档之家› 基于Floyd算法的最短路径问题的求解c++

基于Floyd算法的最短路径问题的求解c++

摘要现实生活中许多实际问题的解决依赖于最短路径的应用,其中比较常用的是floyd 算法。

通过floyd算法使最短路径问题变得简单化。

采用图的邻接矩阵或邻接表实现最短路径问题中图的存储。

采用Visual C++6.0的控制台工程和MFC工程分别实现基于floyd算法求最短路径的应用。

关键词:最短路径;floyd算法;邻接矩阵;MFC工程目录1需求分析 (1)2算法基本原理 (1)2.1邻接矩阵 (1)2.2弗洛伊德算法 (2)3类设计 (2)3.1类的概述 (2)3.2类的接口设计 (3)3.3类的实现 (4)4基于控制台的应用程序 (7)4.1主函数设计 (7)4.2运行结果及分析 (8)5基于MFC的应用程序 (9)5.1图形界面设计 (9)5.1程序代码设计 (11)5.3运行结果及分析 (20)结论 (21)参考文献 (22)1需求分析Floyd算法又称为插点法,是一种用于寻找给定的加权图中多源点之间最短路径的算法。

该算法名称以创始人之一、1978年图灵奖获得者、斯坦福大学计算机科学系教授罗伯特·弗洛伊德命名。

假若要在计算机上建立一个交通咨询系统则可以采用图的结构来表示实际的交通网络。

这个资讯系统可以回答游客提出的各种问题。

例如,一位旅客要从A城到B城,他希望选择一条途中中转次数最少的路线。

假设图中每一站都需要换车,则这个问题反映到图上就是要找一条从顶点A到B所含边的数目最少的路径。

我们只需从顶点A出发对图作广度优先搜索,一旦遇到顶点B就终止。

由此所得广度优先生成树上,从根顶点A到顶点B的路径就是中转次数最少的路径,路径上A与B之间的顶点就是途径中的中转站数。

但是这只是一类最简单的图的最短路径的问题。

有时对于旅客来说,可能更关心的是节省交通费用;对于司机来说里程和速度则是他们感兴趣的信息。

为了在图上标示有关信息可对边赋以权的值,权的值表示两城市间的距离,或图中所需时间,或交通费用等等。

此时路径长度的量度就不再是路径上边的数目,而是路径上边的权值之和。

边赋以权值之后再结合最短路径算法来解决这些实际问题。

Floyd算法是最短路径经典算法中形式较为简单,便于理解的一种。

2算法基本原理2.1 邻接矩阵邻接矩阵(Adjacency Matrix):是表示顶点之间相邻关系的矩阵。

设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]来存储带权有向图。

算法的基本思想是:设置一个n x n的矩阵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:公用的数据和成员函数;};定义对象:类名对象名;可以在类外定义成员函数,在函数名前加上类名,“::”是作用域限定符或称作用域运算符用它说明函数式属于哪个类的。

如下面程序中的void MGraph::CreateMGraph(MGraph &G){函数体}3.2 类的接口设计#include<iostream>#include <string>#include <stdio.h>using namespace std;#define MaxVertexNum 100#define INF 32767class MGraph{private:char vertex[MaxVertexNum]; //顶点信息int edges[MaxVertexNum][MaxVertexNum]; //邻接矩阵int n,e; //顶点数和边数public:void CreateMGraph(MGraph &); //构造有向图void Ppath(int[][100],int,int);void Dispath(int[][100],int[][100],int); //输出最短路径void Floyd(MGraph G); //Floyd算法的具体实现};首先将所需文件名写好,定义类MGraph。

在进行类体构造时将数据char vertex[MaxVertexNum]、int edges[MaxVertexNum][MaxVertexNum]和int n,e定义为私有数据,将成员函数void CreateMGraph(MGraph &)、void Ppath(int[][100],int,int)、void Dispath(int[][100],int[][100],int)和void Floyd(MGraph G)定义为公用的,以便非类体的数据调用函数。

3.3 类的实现void MGraph::CreateMGraph(MGraph &G)//构造有向图{int i,j,k,p;cout<<"请输入顶点数和边数:";cin>>G.n>>G.e;cout<<"请输入顶点元素:";for (i=0;i<G.n;i++){cin>>G.vertex[i];}for (i=0;i<G.n;i++){for (j=0;j<G.n;j++){G.edges[i][j]=INF;if (i==j){G.edges[i][j]=0;}}}for (k=0;k<G.e;k++){cout<<"请输入第"<<k+1<<"条弧头弧尾序号和相应的权值:";cin>>i>>j>>p;G.edges[i][j]=p;}}void MGraph::Ppath(int path[][MaxVertexNum],int i,int j) //Ppath()函数在path中递归输出从顶点vi到vj的最短路径。

{int k;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);}void MGraph::Dispath(int A[][MaxVertexNum],int path[][MaxVertexNum],int n)//输出最短路径的算法{int i,j;for (i=0;i<n;i++){for (j=0;j<n;j++){if (A[i][j]==INF){if (i!=j){printf("从%d到%d没有路径\n",i,j);}}else{printf(" 从%d到%d=>路径长度:%d路径:",i,j,A[i][j]);printf("%d,",i);Ppath(path,i,j);printf("%d\n",j);}}}}void MGraph::Floyd(MGraph G){intA[MaxVertexNum][MaxVertexNum],path[MaxVertexNum][MaxVertexNum];int i,j,k;for (i=0;i<G.n;i++){for (j=0;j<G.n;j++){A[i][j]=G.edges[i][j];path[i][j]=-1;}}for (k=0;k<G.n;k++) // /向vi与vj之间中n次加入中间顶点{for (i=0;i<G.n;i++){for (j=0;j<G.n;j++){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 主函数设计int main(){MGraph G;G.CreateMGraph(G);G.Floyd(G);return 0;}在程序的主函数部分,定义一个MGrapha类的对象G,调用成员函数CreateMGraph()和Floyd()分别完成了采用图的邻接矩阵实现最短路径问题中图的存储和采用Floyd算法求每一对顶点的最短路径的任务。

相关主题