Java利用Dijkstra和Floyd分别求取图的最短路径

Java 利用 Dijkstra 和 Floyd 算法分别求取图的最短路径可以分为以下几个步骤:

1. 建立图的数据结构

首先需要建立用于表示图的数据结构,通常可以使用邻接矩阵或邻接表来表示图。

以邻接矩阵为例,可以定义一个二维数组来表示图,数组中的每一个元素 a[i][j] 表示从节点 i 到节点 j 的边的权值。如果不存在从节点 i 到节点 j 的边,则 a[i][j] 的值设置为一个很大的数(如99999999)或者无穷大。

public class Graph {
    private int[][] edges;  // 图的邻接矩阵
    private int numVertices; // 图中节点的个数

    // 构造函数
    public Graph(int numVertices) {
        this.numVertices = numVertices;
        edges = new int[numVertices][numVertices];
        for (int i = 0; i < numVertices; i++) {
            for (int j = 0; j < numVertices; j++) {
                edges[i][j] = 0; // 初始化矩阵元素为0
            }
        }
    }

    // 添加一条边
    public void addEdge(int source, int destination, int weight) {
        edges[source][destination] = weight;
    }

    // 获取邻接矩阵
    public int[][] getMatrix() {
        return edges;
    }
}

2. Dijkstra 算法求最短路径

Dijkstra 算法是一种单源最短路径算法。它以一个节点为起点,依次计算出到其他节点的最短路径。

Dijkstra 算法的基本思想是:先将起点到各个点之间的距离初始化为 ∞,再通过松弛操作逐一更新各个节点的距离。

在 Dijkstra 算法的过程中,需要维护一个集合 S,存储已经确定了最短距离的节点;同时也需要维护一个数组 dist,dist[v] 表示从起点 s 到节点 v 的最短距离。

public class Dijkstra {
    public static void dijkstra(Graph graph, int source) {
        int[][] edges = graph.getMatrix();
        int numVertices = graph.getNumVertices();
        boolean[] visited = new boolean[numVertices]; // 标记节点是否已经加入集合S
        int[] dist = new int[numVertices]; // 存储从源点到其他节点的最短距离

        // 初始化 dist 数组
        for (int i = 0; i < numVertices; i++) {
            dist[i] = Integer.MAX_VALUE;
            visited[i] = false;
        }

        // 把起点加入集合 S
        dist[source] = 0;

        // 循环直到所有节点都被加入集合 S
        for (int count = 0; count < numVertices - 1; count++) {
            // 在未加入集合 S 的节点中找到距离起点最近的节点
            int u = minDistance(dist, visited);

            // 把节点 u 加入集合 S
            visited[u] = true;

            // 更新 u 的邻接节点的距离
            for (int v = 0; v < numVertices; v++) {
                if (!visited[v] && edges[u][v] != 0 && 
                    dist[u] != Integer.MAX_VALUE && 
                    dist[u] + edges[u][v] < dist[v]) {
                    dist[v] = dist[u] + edges[u][v];
                }
            }
        }

        // 输出最短距离
        for (int i = 0; i < numVertices; i++) {
            System.out.printf("从 %d 到 %d 的最短距离是 %d\n",
                    source, i, dist[i]);
        }
    }

    // 找到未加入集合 S 的节点中距离起点最近的节点
    private static int minDistance(int[] dist, boolean[] visited) {
        int min = Integer.MAX_VALUE, minIndex = -1;

        for (int i = 0; i < dist.length; i++) {
            if (!visited[i] && dist[i] <= min) {
                min = dist[i];
                minIndex = i;
            }
        }

        return minIndex;
    }
}

3. Floyd 算法求最短路径

Floyd 算法是一种多源最短路径算法,它可以计算出任意两个节点之间的最短距离。

Floyd 算法的基本思想是:对于图中的每个节点,求出它与其他节点之间的最短路径。算法采用动态规划的思想,通过一个矩阵来记录任意两个节点之间的最短距离。

public class Floyd {
    public static void floyd(Graph graph) {
        int[][] edges = graph.getMatrix();
        int numVertices = graph.getNumVertices();

        // 构造一个与边权矩阵大小相同的数组,初始为边权矩阵
        int[][] shortestPaths = new int[numVertices][numVertices];

        for (int i = 0; i < numVertices; i++) {
            for (int j = 0; j < numVertices; j++) {
                shortestPaths[i][j] = edges[i][j];
            }
        }

        // 通过中间节点 k 来更新最短路径
        for (int k = 0; k < numVertices; k++) {
            for (int i = 0; i < numVertices; i++) {
                for (int j = 0; j < numVertices; j++) {
                    if (shortestPaths[i][k] + shortestPaths[k][j] < shortestPaths[i][j]) {
                        shortestPaths[i][j] = shortestPaths[i][k] + shortestPaths[k][j];
                    }
                }
            }
        }

        // 输出最短距离
        for (int i = 0; i < numVertices; i++) {
            for (int j = 0; j < numVertices; j++) {
                System.out.printf("从 %d 到 %d 的最短距离是 %d\n",
                        i, j, shortestPaths[i][j]);
            }
        }
    }
}

4. 示例说明

假设有如下图形:

     1
(0)--(1)--(2)
 |   / \   |
6|  /   \  |5
 | /     \ |
(3)-------(4)    9
       2   

使用邻接矩阵表示该图:

    0   1   2   3   4  
0   0   1   6   0   0  
1   1   0   5   2   7  
2   6   5   0   0   3  
3   0   2   0   0   4  
4   0   7   3   4   0  

如果以节点 0 为起点,采用 Dijkstra 算法,则最短路径为:

从 0 到 0 的最短距离是 0
从 0 到 1 的最短距离是 1
从 0 到 2 的最短距离是 6
从 0 到 3 的最短距离是 8
从 0 到 4 的最短距离是 15

如果采用 Floyd 算法,则最短路径为:

从 0 到 0 的最短距离是 0
从 0 到 1 的最短距离是 1
从 0 到 2 的最短距离是 6
从 0 到 3 的最短距离是 8
从 0 到 4 的最短距离是 15
从 1 到 0 的最短距离是 1
从 1 到 1 的最短距离是 0
从 1 到 2 的最短距离是 5
从 1 到 3 的最短距离是 2
从 1 到 4 的最短距离是 7
从 2 到 0 的最短距离是 6
从 2 到 1 的最短距离是 5
从 2 到 2 的最短距离是 0
从 2 到 3 的最短距离是 6
从 2 到 4 的最短距离是 3
从 3 到 0 的最短距离是 8
从 3 到 1 的最短距离是 2
从 3 到 2 的最短距离是 6
从 3 到 3 的最短距离是 0
从 3 到 4 的最短距离是 4
从 4 到 0 的最短距离是 15
从 4 到 1 的最短距离是 7
从 4 到 2 的最短距离是 3
从 4 到 3 的最短距离是 4
从 4 到 4 的最短距离是 0

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java利用Dijkstra和Floyd分别求取图的最短路径 - Python技术站

(0)
上一篇 2023年5月26日
下一篇 2023年5月26日

相关文章

  • java eclipse 出现 xxx cannot be resolved to a type 错误解决方法

    当使用Java Eclipse进行编程时,在某些情况下可能会遇到”xxx cannot be resolved to a type”(xxx无法解析为类型)的错误提示,这通常是由未正确引入相关包或类文件导致的。下面是一个详细的解决方法: 步骤1:检查Java Build Path 在Eclipse中,右键单击Java项目并选择Properties,然后选择J…

    Java 2023年5月20日
    00
  • Java 二维码,QR码,J4L-QRCode 的资料整理

    关于Java二维码的资料整理,我可以提供以下攻略: Java二维码资料整理 什么是二维码/Qr码? 二维码(QR码)是一种由日本发明的二维条码,可以用来快捷、高效地传输信息。与传统的条形码不同,二维码可以储存更多的信息,并且可以包含文字、链接、图像等多种格式。在生活中,二维码已经被广泛使用,例如快递单上的小方块、支付宝扫码支付等。 Java二维码生成库J4L…

    Java 2023年5月20日
    00
  • 浅析AJAX乱码及错误解决方案

    下面给出浅析AJAX乱码及错误解决方案的完整攻略。 理解AJAX乱码产生的原因 在使用AJAX过程中,当后台数据返回为非UTF-8编码格式时,中文字符就会出现乱码。这种情况出现是因为浏览器默认将AJAX的编码格式设置为“ISO-8859-1”,而在后台返回数据未使用UTF-8编码格式的时候,字符就会出现乱码。 AJAX乱码解决方案 1.在后台数据处理时修改编…

    Java 2023年6月15日
    00
  • java中使用interrupt通知线程停止详析

    Java中使用interrupt通知线程停止详析 概述 在Java多线程编程中,有时候需要在某个条件满足时中断线程的执行。Java中提供了一种机制,即通过中断(interrupt)的方式通知线程停止。本文将详细阐述Java中使用interrupt通知线程停止的完整攻略。 了解中断机制 在Java中,线程有一个boolean类型的中断标记,初始值为false。…

    Java 2023年5月25日
    00
  • Eclipse中maven异常Updating Maven Project的统一解决方案

    以下是“Eclipse中maven异常Updating Maven Project的统一解决方案”的完整攻略。 问题背景 在使用Eclipse和Maven进行开发时,我们会发现当我们修改了代码并保存后,Eclipse并不会自动更新Maven项目依赖。当我们手动更新依赖时,有时会遇到”Maven updating”的问题,此时需要符合maven规范的项目结构,…

    Java 2023年5月20日
    00
  • Java通过PropertyDescriptor反射调用set和get方法

    Java通过 PropertyDescriptor 反射调用 set 和 get 方法可以让我们通过字符串的形式来动态地调用一个对象的属性。下面是详细的攻略: 一、引入所需依赖 在项目的 pom.xml 文件中引入 commons-beanutils 依赖,以便使用 PropertyDescriptor 类: <dependency> <g…

    Java 2023年6月15日
    00
  • 使用maven开发springboot项目时pom.xml常用配置(推荐)

    在使用Maven开发Spring Boot项目时,pom.xml文件是非常重要的配置文件。本文将详细讲解pom.xml文件中常用的配置,以及如何使用这些配置来构建Spring Boot项目。 1. 常用配置 以下是pom.xml文件中常用的配置: 1.1 项目信息 <groupId>com.example</groupId> <…

    Java 2023年5月15日
    00
  • 可视化Swing中JTable控件绑定SQL数据源的两种方法深入解析

    以下是“可视化Swing中JTable控件绑定SQL数据源的两种方法深入解析”的完整攻略: 一、JTable控件绑定SQL数据源的必要性分析 JTable控件是Swing框架中常用的数据表格控件,而SQL是大型数据存储和管理的主要方式之一,因此在可视化Swing程序中,将JTable控件与SQL数据源进行绑定,可以实现直接从数据源向JTable中加载数据,也…

    Java 2023年5月20日
    00
合作推广
合作推广
分享本页
返回顶部