Java 语言 最短路径算法 Dijkstra的单源最短路径

Java阿木 发布于 25 天前 3 次阅读


Java实现Dijkstra单源最短路径算法

单源最短路径问题是图论中的一个经典问题,它要求从一个给定的源点出发,找到到达图中所有其他点的最短路径。Dijkstra算法是一种解决单源最短路径问题的有效算法,它适用于边的权重非负的加权无向图或有向图。

本文将围绕Java语言,详细介绍Dijkstra算法的实现,包括算法原理、代码实现以及性能分析。

Dijkstra算法原理

Dijkstra算法的基本思想是维护一个集合S,该集合包含已找到最短路径的顶点。算法开始时,S为空,然后逐步扩大S,直到包含所有顶点。在每一步中,从集合V-S中选择一个顶点u,使得u的估计最短路径长度最小,然后将u加入集合S。

以下是Dijkstra算法的步骤:

1. 初始化:设置源点s的估计最短路径长度为0,其他顶点的估计最短路径长度为无穷大;将所有顶点加入集合V-S。

2. 当V-S不为空时,执行以下步骤:

a. 从V-S中选择一个顶点u,使得u的估计最短路径长度最小。

b. 将u加入集合S。

c. 对于V-S中的每个顶点v,更新v的估计最短路径长度,即:

- 如果d[v] > d[u] + w(u,v),则将d[v]更新为d[u] + w(u,v),其中w(u,v)是顶点u和v之间的边的权重。

3. 当V-S为空时,算法结束。

Java实现

下面是使用Java语言实现的Dijkstra算法:

java

import java.util.Arrays;


import java.util.PriorityQueue;

public class DijkstraAlgorithm {


private static final int INF = Integer.MAX_VALUE;

public static void dijkstra(int[][] graph, int source) {


int n = graph.length;


int[] dist = new int[n];


boolean[] visited = new boolean[n];


Arrays.fill(dist, INF);


dist[source] = 0;

PriorityQueue<int[]> pq = new PriorityQueue<>((a, b) -> a[1] - b[1]);


pq.offer(new int[]{source, 0});

while (!pq.isEmpty()) {


int[] u = pq.poll();


int uNode = u[0];


int uDist = u[1];

if (visited[uNode]) {


continue;


}

visited[uNode] = true;

for (int v = 0; v < n; v++) {


if (graph[uNode][v] != INF && !visited[v]) {


int alt = uDist + graph[uNode][v];


if (alt < dist[v]) {


dist[v] = alt;


pq.offer(new int[]{v, alt});


}


}


}


}

System.out.println("VertextDistance from Source");


for (int i = 0; i < n; i++) {


System.out.println(i + "tt" + dist[i]);


}


}

public static void main(String[] args) {


int[][] graph = {


{0, 4, 0, 0, 0, 0, 0, 8, 0},


{4, 0, 8, 0, 0, 0, 0, 11, 0},


{0, 8, 0, 7, 0, 4, 0, 0, 2},


{0, 0, 7, 0, 9, 14, 0, 0, 0},


{0, 0, 0, 9, 0, 10, 0, 0, 0},


{0, 0, 4, 14, 10, 0, 2, 0, 0},


{0, 0, 0, 0, 0, 2, 0, 1, 6},


{8, 11, 0, 0, 0, 0, 1, 0, 7},


{0, 0, 2, 0, 0, 0, 6, 7, 0}


};

dijkstra(graph, 0);


}


}


性能分析

Dijkstra算法的时间复杂度主要取决于优先队列的操作。在Java中,优先队列通常使用二叉堆实现,其插入和删除操作的时间复杂度均为O(log n)。Dijkstra算法的时间复杂度为O((V+E)log V),其中V是顶点数,E是边数。

对于稀疏图,Dijkstra算法的性能较好。当图中的边数较多时,算法的性能可能会受到影响。

总结

本文介绍了Dijkstra算法的原理和Java实现。通过分析算法的时间复杂度,我们可以了解到Dijkstra算法在处理稀疏图时的优势。在实际应用中,我们可以根据具体问题选择合适的算法来解决问题。