📜  Dijkstra 在Java中使用 PriorityQueue 的最短路径算法

📅  最后修改于: 2022-05-13 01:58:09.475000             🧑  作者: Mango

Dijkstra 在Java中使用 PriorityQueue 的最短路径算法

Dijkstra 的算法与 Prim 的最小生成树算法非常相似。与 Prim 的 MST 一样,我们生成以给定源为根的SPT(最短路径树) 。我们维护两组,一组包含包含在最短路径树中的顶点,另一组包含尚未包含在最短路径树中的顶点。在算法的每一步,我们都会找到另一个集合(尚未包含的集合)中的一个顶点,并且与源的距离最小。

这里 Dijkstra 算法的唯一缺点是,在找到如下所列的最短路径时,我们需要通过整个成本数组来找到成本最低的路径。对于小图来说没什么大不了的,同时对于大图来说也是一个效率问题,因为每次我们在遍历时都需要遍历一个数组。现在我们知道队列可以为我们工作,所以我们将优先级队列的概念应用到这个算法中,以消除一些缺点并使复杂性变得更好。

现在让我们讨论问题陈述,而根据标题,它似乎是一种称为优先级队列的数据结构的纯粹实现,其中涉及算法分析。因此,让我们从下面列出的问题陈述开始,因为整个概念都围绕邻接矩阵表示展开。

问题陈述

给定一个具有节点之间边的邻接表表示的图,任务是使用Java中的 Priority Queue 实现 Dijkstra 的单源最短路径算法。给定一个图和图中的一个源顶点,找到从源到给定图中所有顶点的最短路径。

插图:

Input  : Source = 0
Output : 
     Vertex   Distance from Source
        0                0
        1                4
        2                12
        3                19
        4                21
        5                11
        6                9
        7                8
        8                14

执行:

Java
// Java Program to Implement Dijkstra's Algorithm
// Using Priority Queue
 
// Importing utility classes
import java.util.*;
 
// Main class DPQ
public class GFG {
 
    // Member variables of this class
    private int dist[];
    private Set settled;
    private PriorityQueue pq;
    // Number of vertices
    private int V;
    List > adj;
 
    // Constructor of this class
    public GFG(int V)
    {
 
        // This keyword refers to current object itself
        this.V = V;
        dist = new int[V];
        settled = new HashSet();
        pq = new PriorityQueue(V, new Node());
    }
 
    // Method 1
    // Dijkstra's Algorithm
    public void dijkstra(List > adj, int src)
    {
        this.adj = adj;
 
        for (int i = 0; i < V; i++)
            dist[i] = Integer.MAX_VALUE;
 
        // Add source node to the priority queue
        pq.add(new Node(src, 0));
 
        // Distance to the source is 0
        dist[src] = 0;
 
        while (settled.size() != V) {
 
            // Terminating condition check when
            // the priority queue is empty, return
            if (pq.isEmpty())
                return;
 
            // Removing the minimum distance node
            // from the priority queue
            int u = pq.remove().node;
 
            // Adding the node whose distance is
            // finalized
            if (settled.contains(u))
 
                // Continue keyword skips exwcution for
                // following check
                continue;
 
            // We don't have to call e_Neighbors(u)
            // if u is already present in the settled set.
            settled.add(u);
 
            e_Neighbours(u);
        }
    }
 
    // Method 2
    // To process all the neighbours
    // of the passed node
    private void e_Neighbours(int u)
    {
 
        int edgeDistance = -1;
        int newDistance = -1;
 
        // All the neighbors of v
        for (int i = 0; i < adj.get(u).size(); i++) {
            Node v = adj.get(u).get(i);
 
            // If current node hasn't already been processed
            if (!settled.contains(v.node)) {
                edgeDistance = v.cost;
                newDistance = dist[u] + edgeDistance;
 
                // If new distance is cheaper in cost
                if (newDistance < dist[v.node])
                    dist[v.node] = newDistance;
 
                // Add the current node to the queue
                pq.add(new Node(v.node, dist[v.node]));
            }
        }
    }
 
    // Main driver method
    public static void main(String arg[])
    {
 
        int V = 5;
        int source = 0;
 
        // Adjacency list representation of the
        // connected edges by declaring List class object
        // Declaring object of type List
        List > adj
            = new ArrayList >();
 
        // Initialize list for every node
        for (int i = 0; i < V; i++) {
            List item = new ArrayList();
            adj.add(item);
        }
 
        // Inputs for the GFG(dpq) graph
        adj.get(0).add(new Node(1, 9));
        adj.get(0).add(new Node(2, 6));
        adj.get(0).add(new Node(3, 5));
        adj.get(0).add(new Node(4, 3));
 
        adj.get(2).add(new Node(1, 2));
        adj.get(2).add(new Node(3, 4));
 
        // Calculating the single source shortest path
        GFG dpq = new GFG(V);
        dpq.dijkstra(adj, source);
 
        // Printing the shortest path to all the nodes
        // from the source node
        System.out.println("The shorted path from node :");
 
        for (int i = 0; i < dpq.dist.length; i++)
            System.out.println(source + " to " + i + " is "
                               + dpq.dist[i]);
    }
}
 
// Class 2
// Helper class implementing Comparator interface
// Representing a node in the graph
class Node implements Comparator {
 
    // Member variables of this class
    public int node;
    public int cost;
 
    // Constructors of this class
 
    // Constructor 1
    public Node() {}
 
    // Constructor 2
    public Node(int node, int cost)
    {
 
        // This keyword refers to current instance itself
        this.node = node;
        this.cost = cost;
    }
 
    // Method 1
    @Override public int compare(Node node1, Node node2)
    {
 
        if (node1.cost < node2.cost)
            return -1;
 
        if (node1.cost > node2.cost)
            return 1;
 
        return 0;
    }
}



输出:
The shorted path from node :
0 to 0 is 0
0 to 1 is 8
0 to 2 is 6
0 to 3 is 5
0 to 4 is 3