弗洛伊德算法詳解
說明
- 弗洛伊德算法也是求一個頂點到其他頂點的最短路徑問題,和迪傑斯特拉算法有共同之處,不同處在於迪傑斯特拉算法只是求得某一具體的頂點到其他頂點的最短距離,而弗洛伊德會求出所有的頂點到其他頂點的距離,弗洛伊德會創建一個二維距離數組保存各個頂點到其它頂點的距離,通過不斷的更新這個二維數組,獲得最短的路徑
- 弗洛伊德的核心思想為使用三層循環,第一層循環記錄一個中間頂點,分別遍歷所有的頂點,第二層循環記錄一個開始頂點,分別遍歷所有的頂點,第三層循環記錄終點的頂點,分別遍歷所有的頂點,每次遍歷使用一個變量記錄開始節點經過中間節點到終點節點的路徑權值,如果這個路徑小於開始節點到終點節點的直接路徑權值,則更新開始到終點的路徑為最短
- 弗洛伊德算法時間復雜度為立方階,因為要遍歷所有的情況,動態的更新數組,然后根據更新后的數組再判斷距離的大小
- 弗洛伊德算法比較好理解,因為通過三層循環就能走通從當前節點到其他節點的所有路徑,但是效率不是很高,對於節點數量較多的圖不適用
- 源碼見下
源碼及分析
package algorithm.algorithm.floyd;
import java.util.Arrays;
/**
* @author AIMX_INFO
* @version 1.0
*/
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 = new Graph(vertex.length, vertex, matrix);
graph.floyd();
graph.show();
}
}
class Graph {
//頂點
private char[] vertex;
//各個頂點之間的距離
private int[][] dis;
//前驅頂點
private int[][] pre;
/**
* @param length 頂點個數
* @param vertex 頂點的值
* @param matrix 鄰接矩陣
*/
public Graph(int length, char[] vertex, int[][] matrix) {
this.vertex = vertex;
this.dis = matrix;
this.pre = new int[length][length];
//前驅頂點默認為它自己
for (int i = 0; i < pre.length; i++) {
Arrays.fill(pre[i], i);
}
}
public void show() {
for (int k = 0; k < dis.length; k++) {
for (int i = 0; i < dis.length; i++) {
System.out.print(vertex[pre[k][i]] + "\t");
}
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;
for (int k = 0; k < vertex.length; k++) {
for (int i = 0; i < vertex.length; i++) {
for (int j = 0; j < vertex.length ; j++) {
len = dis[i][k] + dis[k][j];
if (len < dis[i][j]){
dis[i][j] = len;
pre[i][j] = pre[k][j];
}
}
}
}
}
}