求解最小路径是图中很重要的算法,主要有两种迪杰斯特拉算法(Dijkstra)与弗洛伊德算法(Floyd)。
我们用上述两种方法求解以下图的最短路径:
- 迪杰斯特拉算法(Dijkstra):
import java.util.Arrays;
/**
* 最短路径:迪杰斯特拉算法
* 假设:起始点为v0
* @author 13983
*
*/
public class Main {
public static int path[]=new int[9]; //记录每一个顶点在最短路径中的前驱顶点是谁
public static int distance[]=new int [9]; //记录v0到每个顶点的距离
private static final int infinity=65536; //设极限值为65536
public static void main(String[] args) {
/*
* 构造邻接矩阵,根据上图构造,无连接则置为65536
*/
int[][]a={{0,1,5,65536,65536,65536,65536,65536,65536},
{1,0,3,7,5,65536,65536,65536,65536},
{5,3,0,65536,1,7,65536,65536,65536},
{65536,7,65536,0,2,65536,3,65536,65536},
{65536,5,1,2,0,3,6,9,65536},
{65536,65536,7,65536,3,0,65536,5,65536},
{65536,65536,65536,3,6,65536,0,2,7},
{65536,65536,65536,65536,9,5,2,0,4},
{65536,65536,65536,65536,65536,65536,7,4,0},
};
/*
* 使用迪杰斯特拉算法
*/
shortPath_Dijkstra(a);
System.out.println(Arrays.toString(path));
/*
* 假设:终点v8
*/
int n=8;
findPath(path,n);
}
private static void findPath(int[] path,int n) {
while(n!=0){ //如果不是起始点则执行循环
System.out.print("-->v"+n);
n=path[n];
}
System.out.print("-->v"+0);
}
/*
* 迪杰斯特拉算法实现
*/
private static void shortPath_Dijkstra(int[][] a) {
int min,k = 0;
int finals[]=new int [9]; //记录每个顶点是否找到最短路径的标志
//初始化数据
for(int i=0;i<9;i++){
path[i]=0; //初始化path
distance[i]=a[0][i]; //初始化举例
finals[i]=0; //所有顶点都未找到最短路径
}
distance[0]=0; //v0到v0的路径为0
finals[0]=1; //v0找到了最短路径
for(int i=0;i<9;i++){ //主循环 每次求得v0到某个顶点的最短路径
min=infinity;
for(int j=0;j<9;j++){ //寻找离v0最近的点
if(finals[j]==0&&distance[j]<min){
min=distance[j];
k=j;
}
}
finals[k]=1;
for(int w=0;w<9;w++){
//如果经过k顶点的路径比当前的路径端的话
if(finals[w]==0&&min+a[k][w]<distance[w]){
//说明找到了最短路径
distance[w]=min+a[k][w];
path[w]=k;
}
}
}
}
}
结果显示:
- 弗洛伊德(Floyd)算法:
package com.xxt.path;
import java.util.Arrays;
/**
* 最短路径:弗洛伊德算法
*
* @author 13983
*
*/
public class Test {
public static void main(String[] args) {
/*
* 构造邻接矩阵
*/
int[][]a={{0,1,5,65536,65536,65536,65536,65536,65536},
{1,0,3,7,5,65536,65536,65536,65536},
{5,3,0,65536,1,7,65536,65536,65536},
{65536,7,65536,0,2,65536,3,65536,65536},
{65536,5,1,2,0,3,6,9,65536},
{65536,65536,7,65536,3,0,65536,5,65536},
{65536,65536,65536,3,6,65536,0,2,7},
{65536,65536,65536,65536,9,5,2,0,4},
{65536,65536,65536,65536,65536,65536,7,4,0},
};
/*
* 前驱矩阵p
*/
int [][]p=new int[9][9];
/*
* 调用Floyd算法
*/
shortestPath_Floyd(a,p);
System.out.println(Arrays.deepToString(a));
/*
* 根据前驱矩阵,输出最小路径,起始点0,终点8
*/
shortPath(p,0,8);
}
private static void shortPath(int[][] p, int i, int j) {
System.out.print("v"+i);
while(p[i][j]!=i){
System.out.print("-->v"+p[i][j]);
i=p[i][j];
}
}
private static void shortestPath_Floyd(int[][] a, int[][] p) {
/*
* 初始化p
*/
for(int i=0;i<9;i++){
for(int j=0;j<9;j++){
p[i][j]=j;
}
}
for(int i=0;i<9;i++){
for(int j=0;j<9;j++){
for(int w=0;w<9;w++){
if(a[j][w]>a[j][i]+a[i][w]){
//如果i顶点比员两点间路径更短
a[j][w]=a[j][i]+a[i][w];
p[j][w]=p[j][i];
}
}
}
}
}
}
结果显示: