Floyd算法

Floyd算法又称为插点法,是一种利用动态规划的思想寻找给定的加权图中多源点之间最短路径的算法,与Dijkstra算法类似。

原理:每一对顶点 u 和 v,看看是否存在一个顶点 w 使得从 u 到 w 再到 v 比己知的路径更短

步骤如下:加权图 G,边的距离dis[][], 前驱节点记录path[][]

1:初始化 path[i][j] = j;即:初始化所有节点都是直接相连

2:遍历 G 的节点 n1 ,尝试 是否满足 存在两个节点 a,b 使: [a->b] > [a->n1->b], 如果存在那么 修改 dis[a][b] = dis[a][n1]+dis[n1][b] 和 path[a][b]=path[a][n1];(通俗的说就是,查找以当前点为中介点连接两点是否比两点之前的路径更短?)

public static void floyd(int[][] graph){
		int size = graph.length;
		int path[][] = new int[size][size];
		for (int i = 0; i < size; i++){
			for (int j = 0; j < size; j++){
				path[i][j] = j;// 初始化所有节点都是直接相连的即都是 i到j 中间不间隔k
			}
		}
		// 循环遍历每个节点是否有 i到k到j 比 i到j的距离小
		for (int k = 0; k < size; k++){
			for (int i = 0; i < size; i++){
				for (int j = 0; j < size; j++){
					// i到k到j 比 i到j的距离(也有可能是上一个i到k到j)小
					// 记录下 新的 i到j 距离 即 i到k到j的距离
					// 记录下 中转边
					if (graph[i][k] != GraphUtils.MAX 
							&& graph[k][j] != GraphUtils.MAX
							&& graph[i][k] + graph[k][j] < graph[i][j]){
						// 记录最短距离
						graph[i][j] = graph[i][k] + graph[k][j];
						// 记录最短路径
						// i到j 的第一个节点 肯定是 i到k 的第一个节点
						// 这样 path[i][j] 就是 i-k 和 k-j的路径了
						path[i][j] = path[i][k];
					}
				}
			}
		}
		printDis(graph);
		printLine(path, graph);
	}
	
	private static void printDis(int[][] graph){
		int size = graph.length;
		for (int n = 0; n < size; n++){
			for (int i = 0; i < size; i++){
				if (i != n && graph[n][i] != GraphUtils.MAX)
					System.out.printf("%d -> %d:%d , ", n, i, graph[n][i]);
			}
			System.out.println();
		}
	}
	
	private static void printLine(int[][] path, int[][] graph){
		int size = path.length;
		for (int i = 0; i < size; i++){
			for (int j = 0; j < size; j++){
				int x = i;
				if (i == j || graph[x][j] == GraphUtils.MAX)
					continue;
				System.out.printf("from %d to %d: %d", i, j, i);
				while (graph[x][j] != GraphUtils.MAX 
						&& path[x][j] != -1 
						&& path[x][j] != x){
					System.out.printf(" -> %d", path[x][j]);
					x = path[x][j];
				}
				System.out.println();
			}
		}
	}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值