Java实现最短路径算法(Dijkstra算法)

简介: Java实现最短路径算法

Java实现最短路径算法(Dijkstra算法):

import java.util.*;

public class Dijkstra {

    public static void main(String[] args) {
        int[][] graph = {{0, 2, 4, 0, 0, 0},
                         {2, 0, 3, 5, 0, 0},
                         {4, 3, 0, 1, 7, 0},
                         {0, 5, 1, 0, 4, 2},
                         {0, 0, 7, 4, 0, 6},
                         {0, 0, 0, 2, 6, 0}};
        int startNode = 0;
        int[] dist = dijkstra(graph, startNode);
        System.out.println(Arrays.toString(dist));
    }

    public static int[] dijkstra(int[][] graph, int startNode) {
        int n = graph.length;
        int[] dist = new int[n];
        boolean[] visited = new boolean[n];
        Arrays.fill(dist, Integer.MAX_VALUE);
        dist[startNode] = 0;
        for (int i = 0; i < n - 1; i++) {
            int u = findMinDist(dist, visited);
            visited[u] = true;
            for (int v = 0; v < n; v++) {
                if (!visited[v] && graph[u][v] != 0 && dist[u] != Integer.MAX_VALUE && dist[u] + graph[u][v] < dist[v]) {
                    dist[v] = dist[u] + graph[u][v];
                }
            }
        }
        return dist;
    }

    private static int findMinDist(int[] dist, boolean[] visited) {
        int minDist = Integer.MAX_VALUE;
        int minNode = -1;
        for (int i = 0; i < dist.length; i++) {
            if (!visited[i] && dist[i] < minDist) {
                minDist = dist[i];
                minNode = i;
            }
        }
        return minNode;
    }
}

Python实现最短路径算法(Dijkstra算法):

import heapq

def dijkstra(graph, startNode):
    n = len(graph)
    dist = [float('inf')] * n
    visited = [False] * n
    dist[startNode] = 0
    heap = [(0, startNode)]
    while heap:
        (d, u) = heapq.heappop(heap)
        if visited[u]: continue
        visited[u] = True
        for v, w in graph[u]:
            if not visited[v] and dist[u] + w < dist[v]:
                dist[v] = dist[u] + w
                heapq.heappush(heap, (dist[v], v))
    return dist

graph = [[(1, 2), (2, 4)],
         [(0, 2), (2, 3), (3, 5)],
         [(0, 4), (1, 3), (3, 1), (4, 7)],
         [(1, 5), (2, 1), (4, 4), (5, 2)],
         [(2, 7), (3, 4), (5, 6)],
         [(3, 2), (4, 6)]]
startNode = 0
dist = dijkstra(graph, startNode)
print(dist)
  1. Floyd算法

Floyd算法是一种动态规划算法,用于寻找所有节点对之间的最短路径。该算法通过对每对节点之间的距离进行递推,来计算出所有节点之间的最短路径。

Java代码实现:

public static int[][] floyd(int[][] graph) {
    int n = graph.length;
    int[][] dist = new int[n][n];
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            dist[i][j] = graph[i][j];
        }
    }
    for (int k = 0; k < n; k++) {
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                if (dist[i][k] != Integer.MAX_VALUE && dist[k][j] != Integer.MAX_VALUE && dist[i][k] + dist[k][j] < dist[i][j]) {
                    dist[i][j] = dist[i][k] + dist[k][j];
                }
            }
        }
    }
    return dist;
}

Python代码实现:

import sys

def floyd(graph):
    n = len(graph)
    dist = [[0] * n for i in range(n)]
    for i in range(n):
        for j in range(n):
            dist[i][j] = graph[i][j]
    for k in range(n):
        for i in range(n):
            for j in range(n):
                if dist[i][k] != sys.maxsize and dist[k][j] != sys.maxsize and dist[i][k] + dist[k][j] < dist[i][j]:
                    dist[i][j] = dist[i][k] + dist[k][j]
    return dist
  1. Bellman-Ford算法

Bellman-Ford算法是一种动态规划算法,用于解决带有负权边的最短路径问题。该算法通过对每条边进行逐步松弛操作,来计算出从起点到其他节点的最短路径。

Java代码实现:

public static int[] bellmanFord(int[][] graph, int start) {
    int n = graph.length;
    int[] dist = new int[n];
    Arrays.fill(dist, Integer.MAX_VALUE);
    dist[start] = 0;
    
    for (int i = 0; i < n-1; i++) {
        for (int u = 0; u < n; u++) {
            for (int v = 0; v < n; v++) {
                if (graph[u][v] != 0 && dist[u] != Integer.MAX_VALUE && dist[u] + graph[u][v] < dist[v]) {
                    dist[v] = dist[u] + graph[u][v];
                }
            }
        }
    }
    return dist;
}

Python代码实现:

import sys

def bellman_ford(graph, start):
    n = len(graph)
    dist = [sys.maxsize] * n
    dist[start] = 0
    
    for i in range(n-1):
        for u in range(n):
            for v in range(n):
                if graph[u][v] != 0 and dist[u] != sys.maxsize and dist[u] + graph[u][v] < dist[v]:
                    dist[v] = dist[u] + graph[u][v]
    return dist

分析:

  1. Dijkstra算法和Floyd算法适用于无负权边的最短路径问题,而Bellman-Ford算法适用于带有负权边的最短路径问题。
  2. Dijkstra算法的时间复杂度为O(V^2),其中V为节点数,但是可以通过使用优先队列将时间复杂度优化至O(E + VlogV),其中E为边数。Floyd算法的时间复杂度为O(V^3),空间复杂度为O(V^2)。Bellman-Ford算法的时间复杂度为O(VE),其中V为节点数,E为边数。
  3. 在实际应用中,通常情况下使用Dijkstra算法和Floyd算法,因为它们的时间复杂度较低,而且适用范围广。但是,如果存在负权边,则必须使用Bellman-Ford算法。

Java和Python都可以很方便地实现最短路径算法,其中Dijkstra算法是一种基于贪心思想的算法,可以在有向或无向图中找到单源最短路径。Java和Python都有很好的支持数据结构的库,如Java中的Arrays和PriorityQueue,Python中的heapq和list等,可以方便地实现Dijkstra算法。

在Java中,我们使用了一个数组dist来记录从起点到每个节点的最短距离,使用一个布尔数组visited来记录每个节点是否已经被访问过。在每次迭代中,我们选择未访问并且距离起点最近的节点,并将其标记为已访问。然后,我们遍历从该节点出发的所有边,如果该边的目标节点未被访问并且通过该边到达目标节点的距离比已知的最短距离更小,则更新该节点的最短距离。最后,我们返回dist数组,其中包含从起点到每个节点的最短距离。

在Python中,我们使用了一个列表dist来记录从起点到每个节点的最短距离,使用一个布尔列表visited来记录每个节点是否已经被访问过。我们还使用了Python的heapq模块来实现优先队列。在每次迭代中,我们选择未访问并且距离起点最近的节点,并将其标记为已访问。然后,我们遍历从该节点出发的所有边,如果该边的目标节点未被访问并且通过该边到达目标节点的距离比已知的最短距离更小,则更新该节点的最短距离。最后,我们返回dist列表,其中包含从起点到每个节点的最短距离。

目录
相关文章
|
2月前
|
存储 人工智能 算法
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
这篇文章详细介绍了Dijkstra和Floyd算法,这两种算法分别用于解决单源和多源最短路径问题,并且提供了Java语言的实现代码。
91 3
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
|
2月前
|
算法 搜索推荐 Java
java 后端 使用 Graphics2D 制作海报,画echarts图,带工具类,各种细节:如头像切割成圆形,文字换行算法(完美实验success),解决画上文字、图片后不清晰问题
这篇文章介绍了如何使用Java后端技术,结合Graphics2D和Echarts等工具,生成包含个性化信息和图表的海报,并提供了详细的代码实现和GitHub项目链接。
141 0
java 后端 使用 Graphics2D 制作海报,画echarts图,带工具类,各种细节:如头像切割成圆形,文字换行算法(完美实验success),解决画上文字、图片后不清晰问题
|
2月前
|
算法 Java 数据中心
探讨面试常见问题雪花算法、时钟回拨问题,java中优雅的实现方式
【10月更文挑战第2天】在大数据量系统中,分布式ID生成是一个关键问题。为了保证在分布式环境下生成的ID唯一、有序且高效,业界提出了多种解决方案,其中雪花算法(Snowflake Algorithm)是一种广泛应用的分布式ID生成算法。本文将详细介绍雪花算法的原理、实现及其处理时钟回拨问题的方法,并提供Java代码示例。
89 2
|
2月前
|
算法 Java Linux
java制作海报一:java使用Graphics2D 在图片上写字,文字换行算法详解
这篇文章介绍了如何在Java中使用Graphics2D在图片上绘制文字,并实现自动换行的功能。
141 0
|
2月前
|
存储 算法 程序员
迪杰斯特拉(Dijkstra)算法(C/C++)
迪杰斯特拉(Dijkstra)算法(C/C++)
|
2月前
|
算法 Java 测试技术
数据结构 —— Java自定义代码实现顺序表,包含测试用例以及ArrayList的使用以及相关算法题
文章详细介绍了如何用Java自定义实现一个顺序表类,包括插入、删除、获取数据元素、求数据个数等功能,并对顺序表进行了测试,最后还提及了Java中自带的顺序表实现类ArrayList。
31 0
|
4月前
|
设计模式 缓存 算法
揭秘策略模式:如何用Java设计模式轻松切换算法?
【8月更文挑战第30天】设计模式是解决软件开发中特定问题的可重用方案。其中,策略模式是一种常用的行为型模式,允许在运行时选择算法行为。它通过定义一系列可互换的算法来封装具体的实现,使算法的变化与客户端分离。例如,在电商系统中,可以通过定义 `DiscountStrategy` 接口和多种折扣策略类(如 `FidelityDiscount`、`BulkDiscount` 和 `NoDiscount`),在运行时动态切换不同的折扣逻辑。这样,`ShoppingCart` 类无需关心具体折扣计算细节,只需设置不同的策略即可实现灵活的价格计算,符合开闭原则并提高代码的可维护性和扩展性。
67 2
|
4月前
|
安全 算法 Java
java系列之~~网络通信安全 非对称加密算法的介绍说明
这篇文章介绍了非对称加密算法,包括其定义、加密解密过程、数字签名功能,以及与对称加密算法的比较,并解释了非对称加密在网络安全中的应用,特别是在公钥基础设施和信任网络中的重要性。
|
2天前
|
安全 Java API
java如何请求接口然后终止某个线程
通过本文的介绍,您应该能够理解如何在Java中请求接口并根据返回结果终止某个线程。合理使用标志位或 `interrupt`方法可以确保线程的安全终止,而处理好网络请求中的各种异常情况,可以提高程序的稳定性和可靠性。
25 6
|
17天前
|
设计模式 Java 开发者
Java多线程编程的陷阱与解决方案####
本文深入探讨了Java多线程编程中常见的问题及其解决策略。通过分析竞态条件、死锁、活锁等典型场景,并结合代码示例和实用技巧,帮助开发者有效避免这些陷阱,提升并发程序的稳定性和性能。 ####