Floyd算法 最短路径 记录路径
Floyd算法和Dijkstra算法都是最短路径算法。
其中Dijkstra算法一次只能求出一个点的最短路径。
所有点最短路径用Floyd,另外,Floyd可以处理带负边的图。
原理
其实其原理很简单,就是将每一个点都做一次中转,如果经过中转,路径变短那么我们就保存路径和路径长度。
public void floyd(){
// 初始化
int[][] dist = graph.clone();
List<List<String>> paths = new ArrayList<>();
//init
for(int i=0;i< graph.length;i++){
List<String> listString = new ArrayList<>();
for(int j=0;j< graph.length;j++){
listString.add("");
if(dist[i][j]==0){
dist[i][j] = Integer.MAX_VALUE;// 代表路径不通
}
}
paths.add(listString);
}
for(int k=0;k< graph.length;k++){
for(int i=0;i< graph.length;i++){
for(int j=0;j< graph.length;j++){
// 如果路径不通
if(dist[i][k]==Integer.MAX_VALUE||dist[k][j]==Integer.MAX_VALUE){
continue;
}
int haveChangeLen = dist[i][k]+dist[k][j];
// 如果经过k点中转,路径会变短
if(dist[i][j]>haveChangeLen){
dist[i][j] = haveChangeLen;
paths.get(i).set(j,paths.get(i).get(k)+names[k]+"--");
}
}
}
}
}
全部代码
package com.company;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
public class MinSpanTree {
int[][] graph;
String[] names;
public MinSpanTree(int[][] graph, String[] names) {
this.graph = graph;
this.names = names;
}
void prim(){
// 从一顶点出发,直道将所有顶点都生成
int[] arcLen = new int[graph.length];
boolean[] visited = new boolean[graph.length];
int[] relNode = new int[graph.length];
for(int i=0;i< graph.length;i++){
relNode[i]=-1;
}
int visitedLen = 0;
int visitNode = 0;
while (visitedLen!=graph.length){
if(visited[visitNode]){
int min = 0;
int minLen = Integer.MAX_VALUE;
for(int i=0;i< graph.length;i++){
if(!visited[i]&&arcLen[i]!=0){
if(minLen> arcLen[i]){
minLen = arcLen[i];
min = i;
}
}
}
visitNode = min;
}
visitedLen++;
visited[visitNode] = true;
System.out.print(names[visitNode]);
if(relNode[visitNode]!=-1){
System.out.print(" "+names[relNode[visitNode]]+" "+arcLen[visitNode]);
}
System.out.println();
for(int i=0;i< graph.length;i++){
if(!visited[i]&&graph[visitNode][i]!=0){
if(arcLen[i]==0||arcLen[i]>graph[visitNode][i]){
arcLen[i]=graph[visitNode][i];
relNode[i] = visitNode;
}
}
}
}
}
// 克鲁斯卡尔
public void kruskal(){
class ArcNode{
final int i;
final int j;
final int len;
public ArcNode(int i, int j, int len) {
this.i = i;
this.j = j;
this.len = len;
}
}
List<ArcNode> arcNodes = new ArrayList<>();
for(int i=0;i<graph.length;i++){
for(int j=i+1;j< graph.length;j++){
if(graph[i][j]!=0){
arcNodes.add(new ArcNode(i,j,graph[i][j]));
}
}
}
arcNodes.sort(Comparator.comparing(arcNode -> arcNode.len));
boolean[] visited = new boolean[graph.length];
int visitLen = 0;
System.out.println(names[arcNodes.get(0).i]+" "+ names[arcNodes.get(0).j]+" "+arcNodes.get(0).len);
visited[arcNodes.get(0).i]=visited[arcNodes.get(0).j]=true;
visitLen++;
while (visitLen< graph.length){
for(ArcNode arcNode:arcNodes){
if(!visited[arcNode.i]&&visited[arcNode.j]||visited[arcNode.i]&&!visited[arcNode.j]){
System.out.println(names[arcNode.i]+" "+ names[arcNode.j]+" "+arcNode.len);
visited[arcNode.i]=visited[arcNode.j]=true;
break;
}
}
visitLen++;
}
}
public void floyd(){
// 初始化
int[][] dist = graph.clone();
List<List<String>> paths = new ArrayList<>();
//init
for(int i=0;i< graph.length;i++){
List<String> listString = new ArrayList<>();
for(int j=0;j< graph.length;j++){
listString.add("");
if(dist[i][j]==0){
dist[i][j] = Integer.MAX_VALUE;
}
}
paths.add(listString);
}
for(int k=0;k< graph.length;k++){
for(int i=0;i< graph.length;i++){
for(int j=0;j< graph.length;j++){
// 如果路径不同
if(dist[i][k]==Integer.MAX_VALUE||dist[k][j]==Integer.MAX_VALUE){
continue;
}
int haveChangeLen = dist[i][k]+dist[k][j];
// 如果经过k点中转,路径会变短
if(dist[i][j]>haveChangeLen){
dist[i][j] = haveChangeLen;
paths.get(i).set(j,paths.get(i).get(k)+names[k]+"--");
}
}
}
}
// 打印
for(int i=0;i< graph.length;i++){
System.out.println("从"+names[i]+"点出发的最短路径是");
for(int j=0;j< graph.length;j++){
System.out.print("到"+names[j]+"点的最短的路径长度是"+dist[i][j]+" ");
System.out.println("路径是:"+names[i]+"--"+paths.get(i).get(j)+names[j]);
}
}
}
}
class testMinSpanTree{
public static void main(String[] args) {
int[][] graph ={{0,6,1,5,0,0},{6,0,5,0,3,0},{1,5,0,5,6,4},{5,0,5,0,0,2},{0,3,6,0,0,6},{0,0,4,2,6,0}};
String[] names = {"v1","v2","v3","v4","v5","v6"};
MinSpanTree minSpanTree = new MinSpanTree(graph,names);
// minSpanTree.prim();
// minSpanTree.kruskal();
minSpanTree.floyd();
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端