弗洛伊德(Floyd)算法基本介绍

应用场景

image-202211281544229

  1. 胜利乡有7个村庄(A,B,C,D,E,F,G)。
  2. 各个村庄的距离用边线表示(权),比如A-B距离5公里。
  3. 问:如何计算出各村庄到其它各村庄的最短距离?

基本介绍

  1. 和Dijkstra算法一样,弗洛伊德(Floyd)算法也是一种用于寻找给定的加权图中顶点间最短路径的算法。该算法名称以创始人之一、1978 年图灵奖获得者、斯坦福大学计算机科学系教授罗伯特●弗洛伊德命名。
  2. 弗洛伊德算法(Floyd)计算图中各个顶点之间的最短路径。
  3. 迪杰斯特拉算法用于计算图中某-一个顶点到其他顶点的最短路径。
  4. 弗洛伊德算法VS迪杰斯特拉算法:迪杰斯特拉算法通过选定的被访问顶点,求出从出发访问顶点到其他顶点的最短路径;弗洛伊德算法中每一个顶点都是出发访问点,所以需要将每一个顶点看做被访问顶点,求出从每一个顶点到其他顶点的最短路径

思路分析

  1. 设置顶点vi到顶点vk的最短路径已知为Lik,顶点vk到vj的最短路径已知为Lkj,顶点vi到vj的路径为Lij, 则vi到vj的最短路径为: min((Lik+Lkj),Lij), vk 的取值为图中所有顶点,则可获得vi到vj的最短路径。

  2. 至于vi到vk的最短路径Lik或者vk到vj的最短路径Lkj,是以同样的方式获得。

  3. 弗洛伊德(Floyd)算法图解分析。

    image-20221201111053869

Floyd算法解决最短路径问题步骤图解

弗洛伊德算法的步骤:

第一轮循环中,以A(下标为: 0)作 为中间顶点[即把A作为中间顶点的所有情况都进行遍历,就会得到更新距离表和前驱关系],距离表和前驱关系更新为:

image-20221201111119902

  1. 以A顶点作为中间顶点是,C->A->G的距离由N->9, 同理G到C; C->A->B的距离由N->12, 同理B到C。
  2. 更换中间顶点,循环执行操作,直到所有顶点都作为中间顶点更新后,计算结束。

Floyd算法解决最短路径问题-构建图

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
package com.algorithm.floyd;

import java.util.Arrays;

/**
* @author Joker大雄
* @data 2022/12/1 - 11:36
**/
public class FloydAlgorithm {
public static void main(String[] args) {
// 测试图是否创建成功
char[] vertex = {'A', 'B', 'C', 'D', 'E', 'F', 'G'};
// 邻接矩阵创建
int[][] matrix = new int[vertex.length][vertex.length];
// 无法关联
final int N = 65535;
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};

// 创建Graph对象
Graph graph = new Graph(vertex.length, matrix, vertex);
// 遍历
graph.show();
}
}

// 创建图
class Graph {
private char[] vertex; //顶点
private int[][] dis; // 保存从各个顶点出发到其他顶点的距离
private int[][] pre; //保存到达目标顶点的前驱顶点

// 构造器

/**
* @param length 长度
* @param matrix 邻接矩阵
* @param vertex 顶点数组
*/
public Graph(int length, int[][] matrix, char[] vertex) {
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);
}
}

// 显示dis和pre
public void show() {
char[] vertex = {'A', 'B', 'C', 'D', 'E', 'F', 'G'};
for (int i = 0; i < dis.length; i++) {
// 先输出pre
for (int j = 0; j < dis.length; j++) {
System.out.print(vertex[pre[i][j]] + " ");
}
System.out.println();
// 输出dis
for (int j = 0; j < dis.length; j++) {
System.out.print("("+vertex[i]+"到"+vertex[j]+"的最短路径:"+dis[i][j] + ") ");
}
System.out.println();
}
}
}

运行结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
A A A A A A A 
(A到A的最短路径:0) (A到B的最短路径:5) (A到C的最短路径:7) (A到D的最短路径:65535) (A到E的最短路径:65535) (A到F的最短路径:65535) (A到G的最短路径:2)
B B B B B B B
(B到A的最短路径:5) (B到B的最短路径:0) (B到C的最短路径:65535) (B到D的最短路径:9) (B到E的最短路径:65535) (B到F的最短路径:65535) (B到G的最短路径:3)
C C C C C C C
(C到A的最短路径:7) (C到B的最短路径:65535) (C到C的最短路径:0) (C到D的最短路径:65535) (C到E的最短路径:8) (C到F的最短路径:65535) (C到G的最短路径:65535)
D D D D D D D
(D到A的最短路径:65535) (D到B的最短路径:9) (D到C的最短路径:65535) (D到D的最短路径:0) (D到E的最短路径:65535) (D到F的最短路径:4) (D到G的最短路径:65535)
E E E E E E E
(E到A的最短路径:65535) (E到B的最短路径:65535) (E到C的最短路径:8) (E到D的最短路径:65535) (E到E的最短路径:0) (E到F的最短路径:5) (E到G的最短路径:4)
F F F F F F F
(F到A的最短路径:65535) (F到B的最短路径:65535) (F到C的最短路径:65535) (F到D的最短路径:4) (F到E的最短路径:5) (F到F的最短路径:0) (F到G的最短路径:6)
G G G G G G G
(G到A的最短路径:2) (G到B的最短路径:3) (G到C的最短路径:65535) (G到D的最短路径:65535) (G到E的最短路径:4) (G到F的最短路径:6) (G到G的最短路径:0)

Process finished with exit code 0

Floyd算法解决最短路径问题-完整代码

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
package com.algorithm.floyd;

import java.util.Arrays;

/**
* @author Joker大雄
* @data 2022/12/1 - 11:36
**/
public class FloydAlgorithm {
public static void main(String[] args) {
// 测试图是否创建成功
char[] vertex = {'A', 'B', 'C', 'D', 'E', 'F', 'G'};
// 邻接矩阵创建
int[][] matrix = new int[vertex.length][vertex.length];
// 无法关联
final int N = 65535;
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};

// 创建Graph对象
Graph graph = new Graph(vertex.length, matrix, vertex);
// 弗洛伊德算法测试
graph.floyd();
// 遍历
graph.show();
}
}

// 创建图
class Graph {
private char[] vertex; //顶点
private int[][] dis; // 保存从各个顶点出发到其他顶点的距离
private int[][] pre; //保存到达目标顶点的前驱顶点

// 构造器

/**
* @param length 长度
* @param matrix 邻接矩阵
* @param vertex 顶点数组
*/
public Graph(int length, int[][] matrix, char[] vertex) {
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);
}
}

// 显示dis和pre
public void show() {
char[] vertex = {'A', 'B', 'C', 'D', 'E', 'F', 'G'};
for (int i = 0; i < dis.length; i++) {
// 先输出pre
for (int j = 0; j < dis.length; j++) {
System.out.print(vertex[pre[i][j]] + " ");
}
System.out.println();
// 输出dis
for (int j = 0; j < dis.length; j++) {
System.out.print("(" + vertex[i] + "到" + vertex[j] + "的最短路径:" + dis[i][j] + ") ");
}
System.out.println();
}
}

// 弗洛伊德算法
public void floyd() {
int len = 0; // 记录变量保存距离
// 从中间顶点的遍历[A,B,C,D,E,F,G],i是中间顶点的下标
for (int i = 0; i < dis.length; i++) {
// 从j顶点开始出发[A,B,C,D,E,F,G]
for (int j = 0; j < dis.length; j++) {
// 到达k顶点经过[A,B,C,D,E,F,G]
for (int k = 0; k < dis.length; k++) {
// 求出从j出发,经过i到达k的距离
len = dis[j][i] + dis[i][k];
if (len < dis[j][k]) {
// 如果len小于dis[i][j]
dis[j][k] = len; // 更新距离
pre[j][k] = pre[i][k];// 更新前驱顶点
}
}
}
}
}
}

运行结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
A A A F G G A 
(A到A的最短路径:0) (A到B的最短路径:5) (A到C的最短路径:7) (A到D的最短路径:12) (A到E的最短路径:6) (A到F的最短路径:8) (A到G的最短路径:2)
B B A B G G B
(B到A的最短路径:5) (B到B的最短路径:0) (B到C的最短路径:12) (B到D的最短路径:9) (B到E的最短路径:7) (B到F的最短路径:9) (B到G的最短路径:3)
C A C F C E A
(C到A的最短路径:7) (C到B的最短路径:12) (C到C的最短路径:0) (C到D的最短路径:17) (C到E的最短路径:8) (C到F的最短路径:13) (C到G的最短路径:9)
G D E D F D F
(D到A的最短路径:12) (D到B的最短路径:9) (D到C的最短路径:17) (D到D的最短路径:0) (D到E的最短路径:9) (D到F的最短路径:4) (D到G的最短路径:10)
G G E F E E E
(E到A的最短路径:6) (E到B的最短路径:7) (E到C的最短路径:8) (E到D的最短路径:9) (E到E的最短路径:0) (E到F的最短路径:5) (E到G的最短路径:4)
G G E F F F F
(F到A的最短路径:8) (F到B的最短路径:9) (F到C的最短路径:13) (F到D的最短路径:4) (F到E的最短路径:5) (F到F的最短路径:0) (F到G的最短路径:6)
G G A F G G G
(G到A的最短路径:2) (G到B的最短路径:3) (G到C的最短路径:9) (G到D的最短路径:10) (G到E的最短路径:4) (G到F的最短路径:6) (G到G的最短路径:0)

Process finished with exit code 0