弗洛伊德算法详解

弗洛伊德算法详解

说明

  1. 弗洛伊德算法也是求一个顶点到其他顶点的最短路径问题,和迪杰斯特拉算法有共同之处,不同处在于迪杰斯特拉算法只是求得某一具体的顶点到其他顶点的最短距离,而弗洛伊德会求出所有的顶点到其他顶点的距离,弗洛伊德会创建一个二维距离数组保存各个顶点到其它顶点的距离,通过不断的更新这个二维数组,获得最短的路径
  2. 弗洛伊德的核心思想为使用三层循环,第一层循环记录一个中间顶点,分别遍历所有的顶点,第二层循环记录一个开始顶点,分别遍历所有的顶点,第三层循环记录终点的顶点,分别遍历所有的顶点,每次遍历使用一个变量记录开始节点经过中间节点到终点节点的路径权值,如果这个路径小于开始节点到终点节点的直接路径权值,则更新开始到终点的路径为最短
  3. 弗洛伊德算法时间复杂度为立方阶,因为要遍历所有的情况,动态的更新数组,然后根据更新后的数组再判断距离的大小
  4. 弗洛伊德算法比较好理解,因为通过三层循环就能走通从当前节点到其他节点的所有路径,但是效率不是很高,对于节点数量较多的图不适用
  5. 源码见下

源码及分析

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];
                    }
                }
            }
        }
    }
}
posted @   mx_info  阅读(2050)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示