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();
    }
}


posted @   度一川  阅读(322)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端
点击右上角即可分享
微信分享提示