弗洛伊德算法(floyd)

 算法背景:

图中的A,B,C,D,E,F,G,代表7个村庄,边上的权值带表两村庄之间的距离,现在要从某一个村庄,例如G村庄,往另外几个村庄送邮件,问任意一村庄到其他各村庄的最短距离分别是多少?

思路:

该问题实际是求从任一顶点到其余顶点的最短距离,即多源顶点间的距离。可以用弗洛伊德算法求解。

floyd算法求最短距离:

算法思路:

当计算i到j之间的最短距离时,利用一个过渡顶点k,先求出i和k之间的距离,再加上k和j之间的距离,对比得出最短距离(动态规划思想)。图中任意两顶点间都通过过渡顶点计算。

floyd算法需要维护两个二维数组:(i和j均为顶点数组的索引)

  • distance[i][j]: 保存第i个顶点和第j个顶点的最短距离。初始时为图的邻接数组值。
  • prePath[i][j]: 保存第i个顶点到第j个顶点的前驱结点值。

核心代码:

算法分析:

floyd算法中有三层for,最外层为过渡结点,中间层为顶点,最内层为终点,算法复杂度为O(n³)。对稠密图求解最佳,运行一次便可得出所有顶点间的关系。

public void floyd() {
	for(int k = 0; k < n;k++) {//记录中间结点的索引
		for(int i = 0; i < n;i++) {//记录开始结点的索引
			for(int j = 0; j < n;j++) {//记录结束结点的索引
				int len = distance[i][k] + distance[k][j];//“过渡距离”
				if(len < distance[i][j]) {
					distance[i][j] = len;
					prePath[i][j] = prePath[k][j];
				}
			}
		}
	}
}

java代码:

import java.util.*;

public class Floyd {
	public static void main(String[] args) {
		int INF = 0x3f3f3f3f;
		char []vertex = {'A','B','C','D','E','F','G'};
		int [][]edge = new int [][] {
			{INF,5,7,INF,INF,INF,2},
			{5,INF,INF,9,INF,INF,3},
			{7,INF,INF,INF,8,INF,INF},
			{INF,9,INF,INF,INF,4,INF},
			{INF,INF,8,INF,INF,5,4},
			{INF,INF,INF,4,5,INF,6},
			{2,3,INF,INF,4,6,INF}
		};
		graph graph = new graph(vertex, edge);
		graph.floyd();
		graph.printMatrix();
		graph.getAllPath();
	}
}

class graph{
	char vertex[];
	int distance[][];
	int prePath[][];
	int n;//图中顶点的数量
	
	public graph(char[] vertex, int[][] distance) {
		this.vertex = vertex;
		this.distance = distance;
		n = vertex.length;
		prePath = new int[n][n];
		for(int i = 0; i < n;i++) {
			Arrays.fill(prePath[i], i);
		}
	}
	
	public void printMatrix() {
		System.out.println("各顶点间的最短距离为:");
		for(int i = 0; i < n;i++) {
			for(int j = 0; j < n; j++) {
				System.out.printf("(%c->%c:%d)  ",vertex[i],vertex[j],distance[i][j]);
			}
			System.out.println();
		}
	}
	
	public void floyd() {
		for(int k = 0; k < n;k++) {//记录中间结点的索引
			for(int i = 0; i < n;i++) {//记录开始结点的索引
				for(int j = 0; j < n;j++) {//记录结束结点的索引
					int len = distance[i][k] + distance[k][j];//“过渡距离”
					if(len < distance[i][j]) {
						distance[i][j] = len;
						prePath[i][j] = prePath[k][j];
					}
				}
			}
		}
	}
	
	private void getPath(int start,int end) {//start为路径起点,end为终点
		int []temp = new int[n];
		int index = 0;
		int t = end;
		while(true) {
			if(t == start || start == t)break;
			temp[index++] = t;
			t = prePath[start][t];
		}
		temp[index] = start;
		System.out.printf("顶点%c到顶点%c的最短路径为:",vertex[start],vertex[end]);
		for(int i = index; i >= 0;i--) {
			System.out.printf("%c ",vertex[temp[i]]);
		}
		System.out.println();
	}
	
	public void getAllPath() {
		System.out.println("\n所有顶点间最短路径如下:");
		for(int i = 0; i < n;i++) {
			for(int j = 0; j < n;j++) {
				if(i == j)continue;
				getPath(i, j);
			}
			System.out.println();
		}
	}
}

运行输出:

各顶点间的最短距离为:
(A->A:4)  (A->B:5)  (A->C:7)  (A->D:12)  (A->E:6)  (A->F:8)  (A->G:2)  
(B->A:5)  (B->B:6)  (B->C:12)  (B->D:9)  (B->E:7)  (B->F:9)  (B->G:3)  
(C->A:7)  (C->B:12)  (C->C:14)  (C->D:17)  (C->E:8)  (C->F:13)  (C->G:9)  
(D->A:12)  (D->B:9)  (D->C:17)  (D->D:8)  (D->E:9)  (D->F:4)  (D->G:10)  
(E->A:6)  (E->B:7)  (E->C:8)  (E->D:9)  (E->E:8)  (E->F:5)  (E->G:4)  
(F->A:8)  (F->B:9)  (F->C:13)  (F->D:4)  (F->E:5)  (F->F:8)  (F->G:6)  
(G->A:2)  (G->B:3)  (G->C:9)  (G->D:10)  (G->E:4)  (G->F:6)  (G->G:4)  

所有顶点间最短路径如下:
顶点A到顶点B的最短路径为:A B 
顶点A到顶点C的最短路径为:A C 
顶点A到顶点D的最短路径为:A G F D 
顶点A到顶点E的最短路径为:A G E 
顶点A到顶点F的最短路径为:A G F 
顶点A到顶点G的最短路径为:A G 

顶点B到顶点A的最短路径为:B A 
顶点B到顶点C的最短路径为:B A C 
顶点B到顶点D的最短路径为:B D 
顶点B到顶点E的最短路径为:B G E 
顶点B到顶点F的最短路径为:B G F 
顶点B到顶点G的最短路径为:B G 

顶点C到顶点A的最短路径为:C A 
顶点C到顶点B的最短路径为:C A B 
顶点C到顶点D的最短路径为:C E F D 
顶点C到顶点E的最短路径为:C E 
顶点C到顶点F的最短路径为:C E F 
顶点C到顶点G的最短路径为:C A G 

顶点D到顶点A的最短路径为:D F G A 
顶点D到顶点B的最短路径为:D B 
顶点D到顶点C的最短路径为:D F E C 
顶点D到顶点E的最短路径为:D F E 
顶点D到顶点F的最短路径为:D F 
顶点D到顶点G的最短路径为:D F G 

顶点E到顶点A的最短路径为:E G A 
顶点E到顶点B的最短路径为:E G B 
顶点E到顶点C的最短路径为:E C 
顶点E到顶点D的最短路径为:E F D 
顶点E到顶点F的最短路径为:E F 
顶点E到顶点G的最短路径为:E G 

顶点F到顶点A的最短路径为:F G A 
顶点F到顶点B的最短路径为:F G B 
顶点F到顶点C的最短路径为:F E C 
顶点F到顶点D的最短路径为:F D 
顶点F到顶点E的最短路径为:F E 
顶点F到顶点G的最短路径为:F G 

顶点G到顶点A的最短路径为:G A 
顶点G到顶点B的最短路径为:G B 
顶点G到顶点C的最短路径为:G A C 
顶点G到顶点D的最短路径为:G F D 
顶点G到顶点E的最短路径为:G E 
顶点G到顶点F的最短路径为:G F 

你可能感兴趣的:(图,算法,图论,弗洛伊德算法(floyd),多源最短路径)