HOWTO · Java

在 Java 中實現 Dijkstra 演算法

本教程描述並演示了 Java 中的 Dijkstra 演算法。

當找到兩個圖節點之間的最短路徑時,我們可以實現 Dijkstra 演算法,這是一種廣泛使用的演算法。本教程描述了 Dijkstra 演算法的過程,並演示瞭如何在 Java 中實現它。

Dijkstra 演算法

Dijkstra 演算法可以找到從源節點到加權圖中所有節點的最短路徑。最短路徑也可以在圖中的源頂點中找到。

通過 Dijkstra 演算法找到最短路徑將生成具有根源頂點的最短路徑樹 (SPT)。

在 Java 中實現 Dijkstra 演算法時,我們維護兩個列表或集合。第一個包含最短路徑樹中的所有頂點,第二個包含評估階段的頂點以包含在 SPT 中。

我們在每次迭代中從第二個列表中找到一個頂點,它將具有最短路徑。下面是 Dijkstra 演算法的分步過程:

  • 首先,將圖中的所有節點標記為未訪問。
  • 現在,用零初始化起始節點;所有其他無窮大的節點表示最大的數字。
  • 使起始節點成為當前節點。
  • 這個當前節點現在將用於分析其所有未訪問的鄰居節點,然後通過新增邊的權重來計算距離,這將建立當前節點和鄰居節點之間的連線。
  • 比較最近計算的距離和分配給鄰居節點的距離;這將被視為相鄰節點的當前距離。
  • 現在,考慮當前節點周圍尚未訪問的節點,並將當前節點標記為已訪問。
  • 重複這個過程,直到結束節點被標記為已訪問,這意味著 Dijkstra 的演算法已經完成了它的任務。如果結束節點還沒有被標記為已訪問,那麼:
  • 選擇路徑最短的未訪問節點,它將成為新的當前節點。然後從步驟 4 開始重複該過程。

Dijkstra 演算法的虛擬碼

Method DIJKSTRA(G, SV)
    G-> graph;
    SV->starting vertex;
begin
    for every vertex VX in G    //initialization; set the initial path to infinite and current node to 0 or null;
        Distance[VX] <- infinite
        Current[VX] <- NULL
        If V != SV, add VX to Priority Queue    // During the first run, this vertex is the source or starting node
    Distance[SV] <- 0

    while Priority Queue IS NOT EMPTY    // where the neighbor ux has not been extracted  yet from the priority queue
        UX <- Extract MIN Neighbor from Priority Queue
        for each unvisited adjacent_node  VX of UX
            Temporary_Distance <- Distance[UX] + Edge_Weight(UX, VX)
            if Temporary_Distance < Distance[VX]    // A distance with lesser weight (shorter path) from ux is found
                Distance[VX] <- Temporary_Distance
                Current[VX] <- UX    // update the distance of UX
    return Distance[], Current[]
end

在 Java 中使用優先順序佇列實現 Dijkstra 演算法

下面是使用優先順序佇列的 Dijkstra 演算法的 Java 實現:

package delftstack;

import java.util.*;

public class Dijkstra_Algorithm {
  public static void main(String arg[]) {
    int Vertex = 6;
    int source_vertex = 0;
    // representation of graph will be the adjacency list
    List<List<Node> > Node_list = new ArrayList<List<Node> >();
    // For every node in the graph Initialize adjacency list
    for (int i = 0; i < Vertex; i++) {
      List<Node> item = new ArrayList<Node>();
      Node_list.add(item);
    }

    // The edges of the graph
    Node_list.get(0).add(new Node(1, 5));
    Node_list.get(0).add(new Node(4, 2));
    Node_list.get(0).add(new Node(2, 3));
    Node_list.get(1).add(new Node(5, 2));
    Node_list.get(1).add(new Node(4, 3));
    Node_list.get(2).add(new Node(3, 3));
    Node_list.get(2).add(new Node(4, 2));

    // Run the Dijkstra_Algorithm on the graph
    Graph_priority_queue gpq = new Graph_priority_queue(Vertex);
    gpq.Dijkstra_Algo(Node_list, source_vertex);

    // Printing the shortest path from source node to all other the nodes
    System.out.println("The shortest paths from source nodes to all other nodes:");
    System.out.println("Source_Node\t\t"
        + "Other_Node#\t\t"
        + "Path_Distance");
    for (int x = 0; x < gpq.distance.length; x++)
      System.out.println(source_vertex + " \t\t\t " + x + " \t\t\t " + gpq.distance[x]);
  }
}

class Graph_priority_queue {
  int distance[];
  Set<Integer> visited_Node;
  PriorityQueue<Node> Priority_Queue;
  int Vertex; // vertices
  List<List<Node> > node_list;
  // constructor
  public Graph_priority_queue(int Vertex) {
    this.Vertex = Vertex;
    distance = new int[Vertex];
    visited_Node = new HashSet<Integer>();
    Priority_Queue = new PriorityQueue<Node>(Vertex, new Node());
  }

  // Dijkstra's Algorithm implementation
  public void Dijkstra_Algo(List<List<Node> > node_list, int source_vertex) {
    this.node_list = node_list;

    for (int x = 0; x < Vertex; x++) {
      distance[x] = Integer.MAX_VALUE;
    }
    // add the source vertex to the Priority Queue
    Priority_Queue.add(new Node(source_vertex, 0));

    // Distance of the source from source itself is 0
    distance[source_vertex] = 0;
    while (visited_Node.size() != Vertex) {
      // ux is deleted from the Priority Queue which has minimum distance
      int ux = Priority_Queue.remove().dj_node;

      // add the ux node to finalized list which is visited
      visited_Node.add(ux);
      Adjacent_Nodes_Graph(ux);
    }
  }
  // process all the neighbors of the just visited node
  private void Adjacent_Nodes_Graph(int ux) {
    int Edge_Distance = -1;
    int New_Distance = -1;

    // process all neighboring nodes of ux
    for (int x = 0; x < node_list.get(ux).size(); x++) {
      Node vx = node_list.get(ux).get(x);

      //  if current node is not in 'visited'
      if (!visited_Node.contains(vx.dj_node)) {
        Edge_Distance = vx.dj_cost;
        New_Distance = distance[ux] + Edge_Distance;

        // compare the distances
        if (New_Distance < distance[vx.dj_node])
          distance[vx.dj_node] = New_Distance;

        // Add the current vertex to the PriorityQueue
        Priority_Queue.add(new Node(vx.dj_node, distance[vx.dj_node]));
      }
    }
  }
}

// The Class to handle nodes
class Node implements Comparator<Node> {
  public int dj_node;
  public int dj_cost;
  public Node() {}

  public Node(int dj_node, int dj_cost) {
    this.dj_node = dj_node;
    this.dj_cost = dj_cost;
  }
  @Override
  public int compare(Node dj_node1, Node dj_node2) {
    if (dj_node1.dj_cost < dj_node2.dj_cost)
      return -1;
    if (dj_node1.dj_cost > dj_node2.dj_cost)
      return 1;
    return 0;
  }
}

上面的程式碼將使用 Java 中的 Dijkstra 演算法給出給定圖的最短路徑。

輸出:

The shortest paths from source nodes to all other nodes:
Source_Node    Other_Node#    Path_Distance
0              0              0
0              1              5
0              2              3
0              3              6
0              4              2
0              5              7

在 Java 中使用鄰接矩陣實現 Dijkstra 演算法

這是使用鄰接矩陣的 Dijkstra 演算法的 Java 實現:

package delftstack;

// Dijkstra's Algorithm using Adjacency matrix  in Java

public class Dijkstra_Algorithm {
  public static void dijkstra_algo(int[][] Input_Graph, int source_node) {
    int Node_Count = Input_Graph.length;
    boolean[] Vertex_Visited = new boolean[Node_Count];
    int[] Node_Distance = new int[Node_Count];
    for (int x = 0; x < Node_Count; x++) {
      Vertex_Visited[x] = false;
      Node_Distance[x] = Integer.MAX_VALUE;
    }

    // Distance of the source node to itself is zero
    Node_Distance[source_node] = 0;
    for (int x = 0; x < Node_Count; x++) {
      // Updating the distance between the source vertex and neighboring vertex
      int ux = findMinDistance(Node_Distance, Vertex_Visited);
      Vertex_Visited[ux] = true;

      // Updating all the neighboring vertices distances
      for (int vx = 0; vx < Node_Count; vx++) {
        if (!Vertex_Visited[vx] && Input_Graph[ux][vx] != 0
            && (Node_Distance[ux] + Input_Graph[ux][vx] < Node_Distance[vx])) {
          Node_Distance[vx] = Node_Distance[ux] + Input_Graph[ux][vx];
        }
      }
    }
    for (int x = 0; x < Node_Distance.length; x++) {
      System.out.println(String.format("Distance from the source node %s to the node %s is %s",
          source_node, x, Node_Distance[x]));
    }
  }

  // Finding the shortest distance
  private static int findMinDistance(int[] Node_Distance, boolean[] Vertex_Visited) {
    int Minimum_Distance = Integer.MAX_VALUE;
    int Minimum_Distance_Vertex = -1;
    for (int x = 0; x < Node_Distance.length; x++) {
      if (!Vertex_Visited[x] && Node_Distance[x] < Minimum_Distance) {
        Minimum_Distance = Node_Distance[x];
        Minimum_Distance_Vertex = x;
      }
    }
    return Minimum_Distance_Vertex;
  }

  public static void main(String[] args) {
    int source_node = 0;
    int Input_Graph[][] = new int[][] {{0, 0, 3, 2, 0, 0, 1}, {0, 0, 2, 0, 4, 1, 0},
        {1, 0, 0, 3, 3, 0, 0}, {2, 0, 1, 0, 5, 0, 1}, {0, 0, 0, 4, 0, 2, 3}, {0, 3, 0, 1, 2, 0, 1},
        {0, 0, 0, 3, 0, 0, 4}};
    Dijkstra_Algorithm Demo = new Dijkstra_Algorithm();
    Demo.dijkstra_algo(Input_Graph, source_node);
  }
}

上面的程式碼將使用 Java 中的 Dijkstra 演算法在鄰接矩陣中輸出給定圖的最短路徑。

輸出:

Distance from the source node 0 to the node 0 is 0
Distance from the source node 0 to the node 1 is 11
Distance from the source node 0 to the node 2 is 3
Distance from the source node 0 to the node 3 is 2
Distance from the source node 0 to the node 4 is 6
Distance from the source node 0 to the node 5 is 8
Distance from the source node 0 to the node 6 is 1

我們可以使用 Dijkstra 演算法的兩種方法來計算使用 Java 的圖的最短路徑。