package net.datastructures;
/**
* Dijkstra's algorithm for the single-source shortest path problem in
* an undirected graph whose edges have integer weights.
*
*
To execute the algorithm, use the {@link
* #execute(Graph,Vertex,Object) execute} method, and then make
* subsequent calls to the {@link #getDist(Vertex) getDist} method to
* obtain the shortest distance from the start to any given vertex.
*
* @author Roberto Tamassia, Michael Goodrich, Eric Zamore
*/
/* Dijkstra's algorithm for the single-source shortest path problem
* in an undirected graph whose edges have non-negative integer weights. */
public class Dijkstra {
/** Infinity value. */
protected static final Integer INFINITE = Integer.MAX_VALUE;
/** Input graph. */
protected Graph graph;
/** Decoration key for edge weights */
protected Object WEIGHT;
/** Decoration key for vertex distances */
protected Object DIST = new Object();
/** Decoration key for entries in the priority queue */
protected Object ENTRY = new Object();
/** Auxiliary priority queue. */
protected AdaptablePriorityQueue> Q;
/** Executes Dijkstra's algorithm.
* @param g Input graph
* @param s Source vertex
* @param w Weight decoration object */
public void execute(Graph g, Vertex s, Object w) {
graph = g;
WEIGHT = w;
DefaultComparator dc = new DefaultComparator();
Q = new HeapAdaptablePriorityQueue>(dc);
dijkstraVisit(s);
}
/** Get the distance of a vertex from the source vertex.
* This method returns the length of a shortest path from the source
* to u after {@link #execute(Graph,Vertex,Object) execute}
* has been called.
*
* @param u Start vertex for the shortest path tree */
public int getDist(Vertex u) {
return (Integer) u.get(DIST);
}
/** The actual execution of Dijkstra's algorithm.
* @param v source vertex.
*/
protected void dijkstraVisit (Vertex v) {
// store all the vertices in priority queue Q
for (Vertex u: graph.vertices()) {
int u_dist;
if (u==v)
u_dist = 0;
else
u_dist = INFINITE;
Entry> u_entry = Q.insert(u_dist, u); // autoboxing
u.put(ENTRY, u_entry);
}
// grow the cloud, one vertex at a time
while (!Q.isEmpty()) {
// remove from Q and insert into cloud a vertex with minimum distance
Entry> u_entry = Q.min();
Vertex u = u_entry.getValue();
int u_dist = u_entry.getKey();
Q.remove(u_entry); // remove u from the priority queue
u.put(DIST,u_dist); // the distance of u is final
u.remove(ENTRY); // remove the entry decoration of u
if (u_dist == INFINITE)
continue; // unreachable vertices are not processed
// examine all the neighbors of u and update their distances
for (Edge e: graph.incidentEdges(u)) {
Vertex z = graph.opposite(u,e);
Entry> z_entry
= (Entry>) z.get(ENTRY);
if (z_entry != null) { // check that z is in Q, i.e., not in the cloud
int e_weight = (Integer) e.get(WEIGHT);
int z_dist = z_entry.getKey();
if ( u_dist + e_weight < z_dist ) // relaxation of edge e = (u,z)
Q.replaceKey(z_entry, u_dist + e_weight);
}
}
}
}
} // end of Dijkstra class