1.弗洛伊德(Floyd)算法介绍:
(1)和Dijkstra算法一样,弗洛伊德算法也是一种用于寻找给定的加权图中顶点间最短路径的算法,与迪杰斯特拉算法的区别是:迪杰斯特拉算法通过选定的被访问点,求出从出发访问顶点到其他顶点的最短路径.弗洛伊德算法中每一个顶点都是出发访问点,所以需要将每一个顶点看做被访问顶点,求出每一个顶点到其他顶点的最短路径.
2.思路分析
设置顶点vi到顶点vk的最短路径已知为lik,顶点vk到vj的最短路径已知为lkj,顶点vi到vk的路径为Lij,则vi到vj的最短路径为:min((lik+lkj),lij),vk的取值为所有的顶点,则可获得vi到vj的最短路径.
接下里用图例进行一下说明:

上图的N表示不可以直接到达
弗洛伊的算法的步骤:
第一轮循环中,以A(下标为0),作为中间顶点,即把A作为中间顶点的所有情况都进行比那里,就会得到更新的距离表和前驱关系表
分析以A为顶点的所有情况(单向的):
CAG距离为9
CAB距离为12
BAG距离为7
更新的距离表和前驱关系表
此次以A为顶点,依次将所有的点作为顶点,找出最小值即可
3实战
案例:
代码实现:
package com.self.tenAlgorithm;
import java.util.Arrays;
public class FloydAlgorithm {
final static int N = 65535;
public static void main(String[] args) {
char[] vertex = {'A','B','C','D','E','F','G'};
//创建邻接矩阵
int[][] matrix = new int[vertex.length][vertex.length];
matrix[0] = new int[]{0,5,7,N,N,N,2};
matrix[1] = new int[]{5,0,N,9,N,N,3};
matrix[2] = new int[]{7,N,0,N,8,N,N};
matrix[3] = new int[]{N,9,N,0,N,4,N};
matrix[4] = new int[]{N,N,8,N,0,5,4};
matrix[5] = new int[]{N,N,N,4,5,0,6};
matrix[6] = new int[]{2,3,N,N,4,6,0};
Graph0 graph = new Graph0(vertex, vertex.length,matrix);
graph.floyd();
graph.show();
}
}
//创建图
class Graph0{
private char[] vertex; //存放顶点属主
private int[][] dis; //保存,从各个顶点出发到其他顶点的距离,最后的结果,也是保留在该数组
private int[][] pre; //保存到达目标顶点的前驱节点
/**
* 功能: 构造器
* @param vertex 顶点数组
* @param length 大小
* @param matrix 领接矩阵
*/
public Graph0(char[] vertex, int length,int[][] matrix) {
this.vertex = vertex;
this.dis = matrix;
this.pre = new int[length][length];
//对pre数组初始化,注意存放的是前驱顶点的下标
for (int i = 0; i < length; i++) {
Arrays.fill(pre[i],i);
}
}
/**
* 功能:显示pre数组和dis数组
*/
public void show(){
char[] vertex = {'A','B','C','D','E','F','G'};
for (int k = 0; k < dis.length; k++) {
//先将pre数组输出的一行
for (int i = 0; i < dis.length; i++) {
System.out.print(vertex[pre[k][i]]+" ");
}
System.out.println();
for (int i = 0; i < dis.length; i++) {
System.out.print("("+vertex[k]+"到"+vertex[i]+"的最短路径是"+dis[k][i]+") ");
}
System.out.println();
System.out.println();
}
}
/**
* 弗洛伊德算法实现
*/
public void floyd(){
int len = 0; //变量保存距离
//对中间顶点遍历 k就是中间顶点的下标
for (int k = 0; k < dis.length; k++) {
//从i顶点开始出发
for (int i = 0; i < dis.length; i++) {
//到达j顶点
for (int j = 0; j < dis.length; j++) {
len = dis[i][k] + dis[k][j];
if(len < dis[i][j]){
dis[i][j] = len; //更新距离
pre[i][j] = pre[k][j]; //更新前驱节点
}
}
}
}
}
}