1、Floyd算法
原理:图中任意两点之间的最短距离等于两点之间的直接距离和经过其他中间节点的距离之和的最小距离,即D[i][j] = min{ D[i][j] , D[i][k] + D[k][j] },Floyd通常用来求所有顶点到所有顶点的最短路径。
代码如下:
#include "stdafx.h" #include <iostream.h> #include <stdlib.h> #pragma warning(disable:4786) #include <queue> #include <stack> #include <set> #include <vector> using namespace std; const int n=5; void ShortestPath_Floyd(int a[][n],int D[][n],int P[][n]) { int i,j,k; //初始化 for (i=0;i<n;i++) for (j=0;j<n;j++) { D[i][j]=a[i][j]; P[i][j]=j; } for (k=0;k<n;k++) for(i=0;i<n;i++) for (j=0;j<n;j++) if(D[i][j]>D[i][k]+D[k][j]) { D[i][j]=D[i][k]+D[k][j]; //更新最小权值和 P[i][j]=P[i][k]; //更新路径 } } int main(int argc, char* argv[]) { //邻接矩阵5*5,节点0~8 int a[n][n]={ 0,1,4,30,5, 1,0,10,37,2, 4,10,0,20,12, 3,3,20,0,15, 5,2,12,15,0 }; int P[n][n]; //保存最短路径节点 int D[n][n]; //保存最短路径权值和 int k; ShortestPath_Floyd(a,D,P); //打印最短路径 for (int i=0;i<n;i++) { for (int j=i+1;j<n;j++) { cout<<"v"<<i<<"-"<<"v"<<j<<" weight: "<<D[i][j]; k=P[i][j]; cout<<"\tpath: "<<i; while(k!=j) { cout<<" -> "<<k; k=P[k][j]; } cout<<" -> "<<j<<endl; } cout<<endl; } return 0; }
2、Dijkstra算法
原理;D算法并不是一下子就求出顶点v0到vi的最短路径,而是一步步先求出他们之间的顶点的最短路径,过程中都是基于已经求出的最短路径基础上,求得更远顶点的最短路径,最终得到结果。
#include "stdafx.h" #include <iostream.h> #include <stdlib.h> #pragma warning(disable:4786) #include <queue> #include <stack> #include <set> #include <vector> using namespace std; const int n=5; const int MAXVEX=65536; void ShortestPath_Dijkstra(int a[][n],int v0,int D[n],int P[n]) { int i,j,k,min=MAXVEX; int final[n]; //标记是否已求得最短路径 //初始化 for(i=0;i<n;i++) { final[i]=0; D[i]=a[v0][i]; P[i]=0; } D[v0]=0; //v0到v0路径为0 final[v0]=1; //循环找出v0到某个顶点v的最短路径 for (i=0;i<n;i++) { min=MAXVEX; for (j=0;j<n;j++) { if (!final[j]&&D[j]<min) { min=D[j]; //j节点距离v0更近 k=j; } } final[k]=1; //标记已访问过 //修正当前最短最短距离 for (j=0;j<n;j++) { if (!final[j]&&(min+a[k][j])<D[j]) { P[j]=k; D[j]=min+a[k][j]; } } } } int main(int argc, char* argv[]) { //邻接矩阵5*5,节点0~8 int a[n][n]={ 0,1,4,30,5, 1,0,10,37,2, 4,10,0,20,12, 3,3,20,0,15, 5,2,12,15,0 }; int P[n]; //保存最短路径节点 int D[n]; //保存最短路径权值和 int v0=0; //起始节点 int k[n],j=0; ShortestPath_Dijkstra(a,v0,D,P); //打印最短路径 for (int i=0;i<n;i++) { cout<<"v0-v"<<i<<" weight: "<<D[i]; cout<<"\tpath:v0"; k[j]=P[i]; while(k[j]!=0) { k[j+1]=P[k[j]]; j++; } //采用逆向输出数组内容打印最短路径 for(j--;j>=0;j--) cout<<"->v"<<k[j]; j=0; cout<<"->v"<<i<<endl; } cout<<endl; return 0; }