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日

相关文章

  • mybatis-plus主键生成策略

    mybatis-plus主键生成策略可以通过注解或配置文件进行设置,下面将详细讲解。 1. 注解方式设置主键生成策略 在实体类中使用@TableId注解可以设置主键生成方式。其属性type表示主键生成类型,取值范围为枚举类IdType中的枚举值,包括AUTO、NONE、INPUT、ID_WORKER、UUID、ID_WORKER_STR。其中,ID_WORK…

    Java 2023年5月19日
    00
  • 关于Java中数组切片的几种方法(获取数组元素)

    首先来讲一下什么是数组切片。在Java中,数组是一组相同类型的数据所组成的有序集合。数组切片指的是从一个数组中截取一个区间来创建一个新的数组。 获取数组元素,即获取数组中的一部分元素。下面将介绍几种Java中获取数组元素的方法。 1. 直接用”[]”操作符 可以使用下标操作符”[]”来获取数组中的某个位置上的元素,例如: int[] arr = {1, 2,…

    Java 2023年5月26日
    00
  • Scala文件操作示例代码讲解

    我们来详细讲解一下“Scala文件操作示例代码讲解”的完整攻略。 概述 在Scala程序中,文件操作是非常常见的操作。Scala提供了一些简单易用的API帮助我们在程序中进行文件操作。本攻略将会详细讲解如何在Scala程序中进行简单的文件操作,包括如何读取文件、写入文件、拷贝文件和删除文件。 读取文件 Scala的io包中提供了File类,可以用来表示文件或…

    Java 2023年5月20日
    00
  • Java中高效判断数组中是否包含某个元素的几种方法

    下面来详细讲解Java中高效判断数组中是否包含某个元素的几种方法。 问题描述 在Java中的开发中经常需要判断一个数组中是否包含某个元素,这是一个非常常见的需求。但是在实践中,我们需要选择高效的方法来完成这个任务,以尽快地得到结果,提高程序的运行效率和响应速度。 方法一:使用循环判断 使用循环逐一遍历数组中的元素,对每个元素和目标元素进行比较,如果相同,则说…

    Java 2023年5月26日
    00
  • SpringMVC拦截器快速掌握上篇

    下面是关于“SpringMVC拦截器快速掌握上篇”的完整攻略,希望能够对您有所帮助。 什么是SpringMVC拦截器 在SpringMVC框架中,拦截器是一个非常重要的组件,它可以让我们在请求到达Controller之前或者返回结果给客户端之前进行一些统一处理,比如日志记录、权限校验等。 SpringMVC拦截器的配置 配置SpringMVC拦截器很简单,只…

    Java 2023年5月16日
    00
  • Mybatis Plus使用XML编写动态sql的超简易方法

    下面详细讲解”Mybatis Plus使用XML编写动态SQL的超简易方法”。 简介 Mybatis Plus是Mybatis的增强工具,可以用来简化Mybatis的开发。Mybatis Plus默认使用了entity的字段映射表中的字段,但是在实际开发过程中,我们经常会遇到重用entity映射表中同一个字段做不同的条件查询的情况,这时候我们就需要用XML来…

    Java 2023年5月20日
    00
  • Java中的静态内部类是什么?

    Java中的静态内部类是一种内部类,它具有访问外部类的静态成员变量和方法的能力。它与外部类的静态成员是相似的,可以通过类名直接访问。 定义静态内部类 静态内部类的定义方式与成员内部类的定义方式类似,只是需要在内部类名称前面加上static关键字。以下是一个示例: public class OuterClass { private static String …

    Java 2023年4月27日
    00
  • spring+mybatis实现图书管理系统

    以下是“spring+mybatis实现图书管理系统”的完整攻略。 1. 环境准备 首先需要准备好开发环境,包括以下工具和框架: JDK(Java Development Kit): 用于编译和运行Java程序的开发工具包。 Eclipse(或其他Java开发工具):用于编写和调试Java代码的集成开发环境(IDE)。 Maven:Java项目的构建工具,用…

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