2020 */
2121public class Dijkstra {
2222
23- private static Map <Graph .Vertex <Integer >, Graph .CostVertexPair <Integer >> costs = null ;
24- private static Map <Graph .Vertex <Integer >, Set <Graph .Edge <Integer >>> paths = null ;
25- private static Queue <Graph .CostVertexPair <Integer >> unvisited = null ;
26-
2723 private Dijkstra () { }
2824
29- public static Map <Graph .Vertex <Integer >, Graph .CostPathPair <Integer >> getShortestPaths (Graph <Integer > g , Graph .Vertex <Integer > start ) {
30- getShortestPath (g , start , null );
25+ public static Map <Graph .Vertex <Integer >, Graph .CostPathPair <Integer >> getShortestPaths (Graph <Integer > graph , Graph .Vertex <Integer > start ) {
26+ final Map <Graph .Vertex <Integer >, Set <Graph .Edge <Integer >>> paths = new HashMap <Graph .Vertex <Integer >, Set <Graph .Edge <Integer >>>();
27+ final Map <Graph .Vertex <Integer >, Graph .CostVertexPair <Integer >> costs = new HashMap <Graph .Vertex <Integer >, Graph .CostVertexPair <Integer >>();
28+ getShortestPath (graph , start , null , paths , costs );
3129 Map <Graph .Vertex <Integer >, Graph .CostPathPair <Integer >> map = new HashMap <Graph .Vertex <Integer >, Graph .CostPathPair <Integer >>();
3230 for (Graph .CostVertexPair <Integer > pair : costs .values ()) {
3331 int cost = pair .getCost ();
@@ -42,57 +40,69 @@ public static Graph.CostPathPair<Integer> getShortestPath(Graph<Integer> graph,
4240 if (graph == null )
4341 throw (new NullPointerException ("Graph must be non-NULL." ));
4442
45- // Reset variables
46- costs = null ;
47- paths = null ;
48- unvisited = null ;
43+ // Dijkstra's algorithm only works on positive cost graphs
44+ boolean hasNegativeEdge = checkForNegativeEdges (graph .getVerticies ());
45+ if (hasNegativeEdge )
46+ throw (new IllegalArgumentException ("Negative cost Edges are not allowed." ));
47+
48+ final Map <Graph .Vertex <Integer >, Set <Graph .Edge <Integer >>> paths = new HashMap <Graph .Vertex <Integer >, Set <Graph .Edge <Integer >>>();
49+ final Map <Graph .Vertex <Integer >, Graph .CostVertexPair <Integer >> costs = new HashMap <Graph .Vertex <Integer >, Graph .CostVertexPair <Integer >>();
50+ return getShortestPath (graph , start , end , paths , costs );
51+ }
52+
53+ private static Graph .CostPathPair <Integer > getShortestPath (Graph <Integer > graph ,
54+ Graph .Vertex <Integer > start , Graph .Vertex <Integer > end ,
55+ Map <Graph .Vertex <Integer >, Set <Graph .Edge <Integer >>> paths ,
56+ Map <Graph .Vertex <Integer >, Graph .CostVertexPair <Integer >> costs ) {
57+ if (graph == null )
58+ throw (new NullPointerException ("Graph must be non-NULL." ));
4959
5060 // Dijkstra's algorithm only works on positive cost graphs
5161 boolean hasNegativeEdge = checkForNegativeEdges (graph .getVerticies ());
5262 if (hasNegativeEdge )
5363 throw (new IllegalArgumentException ("Negative cost Edges are not allowed." ));
5464
55- paths = new HashMap <Graph .Vertex <Integer >, Set <Graph .Edge <Integer >>>();
5665 for (Graph .Vertex <Integer > v : graph .getVerticies ())
5766 paths .put (v , new LinkedHashSet <Graph .Edge <Integer >>());
5867
59- costs = new HashMap <Graph .Vertex <Integer >, Graph .CostVertexPair <Integer >>();
6068 for (Graph .Vertex <Integer > v : graph .getVerticies ()) {
6169 if (v .equals (start ))
6270 costs .put (v , new Graph .CostVertexPair <Integer >(0 , v ));
6371 else
6472 costs .put (v , new Graph .CostVertexPair <Integer >(Integer .MAX_VALUE , v ));
6573 }
6674
67- unvisited = new PriorityQueue <Graph .CostVertexPair <Integer >>();
68- unvisited .addAll (costs .values ()); // Shallow copy which is O(n log n)
75+ final Queue <Graph .CostVertexPair <Integer >> unvisited = new PriorityQueue <Graph .CostVertexPair <Integer >>();
76+ unvisited .add (costs .get (start ));
77+
78+ while (!unvisited .isEmpty ()) {
79+ final Graph .CostVertexPair <Integer > pair = unvisited .remove ();
80+ final Graph .Vertex <Integer > vertex = pair .getVertex ();
6981
70- Graph .Vertex <Integer > vertex = start ;
71- while (true ) {
7282 // Compute costs from current vertex to all reachable vertices which haven't been visited
7383 for (Graph .Edge <Integer > e : vertex .getEdges ()) {
74- Graph .CostVertexPair <Integer > pair = costs .get (e .getToVertex ()); // O(log n )
75- Graph .CostVertexPair <Integer > lowestCostToThisVertex = costs .get (vertex ); // O(log n )
76- int cost = lowestCostToThisVertex .getCost () + e .getCost ();
77- if (pair .getCost () == Integer .MAX_VALUE ) {
84+ final Graph .CostVertexPair <Integer > toPair = costs .get (e .getToVertex ()); // O(1 )
85+ final Graph .CostVertexPair <Integer > lowestCostToThisVertex = costs .get (vertex ); // O(1 )
86+ final int cost = lowestCostToThisVertex .getCost () + e .getCost ();
87+ if (toPair .getCost () == Integer .MAX_VALUE ) {
7888 // Haven't seen this vertex yet
79- pair .setCost (cost );
8089
8190 // Need to remove the pair and re-insert, so the priority queue keeps it's invariants
82- unvisited .remove (pair ); // O(n)
83- unvisited .add (pair ); // O(log n)
91+ unvisited .remove (toPair ); // O(n)
92+ toPair .setCost (cost );
93+ unvisited .add (toPair ); // O(log n)
8494
8595 // Update the paths
8696 Set <Graph .Edge <Integer >> set = paths .get (e .getToVertex ()); // O(log n)
8797 set .addAll (paths .get (e .getFromVertex ())); // O(log n)
8898 set .add (e );
89- } else if (cost < pair .getCost ()) {
99+ } else if (cost < toPair .getCost ()) {
90100 // Found a shorter path to a reachable vertex
91- pair .setCost (cost );
92101
93102 // Need to remove the pair and re-insert, so the priority queue keeps it's invariants
94- unvisited .remove (pair ); // O(n)
95- unvisited .add (pair ); // O(log n)
103+ unvisited .remove (toPair ); // O(n)
104+ toPair .setCost (cost );
105+ unvisited .add (toPair ); // O(log n)
96106
97107 // Update the paths
98108 Set <Graph .Edge <Integer >> set = paths .get (e .getToVertex ()); // O(log n)
@@ -106,24 +116,12 @@ public static Graph.CostPathPair<Integer> getShortestPath(Graph<Integer> graph,
106116 if (end != null && vertex .equals (end )) {
107117 // If we are looking for shortest path, we found it.
108118 break ;
109- } else if (unvisited .size () > 0 ) {
110- // If there are other vertices to visit (which haven't been visited yet)
111- Graph .CostVertexPair <Integer > pair = unvisited .remove (); // O(log n)
112- vertex = pair .getVertex ();
113- if (pair .getCost () == Integer .MAX_VALUE ) {
114- // If the only edge left to explore has MAX_VALUE then it
115- // cannot be reached from the starting vertex
116- break ;
117- }
118- } else {
119- // No more edges to explore, we are done.
120- break ;
121119 }
122120 }
123121
124122 if (end != null ) {
125- Graph .CostVertexPair <Integer > pair = costs .get (end );
126- Set <Graph .Edge <Integer >> set = paths .get (end );
123+ final Graph .CostVertexPair <Integer > pair = costs .get (end );
124+ final Set <Graph .Edge <Integer >> set = paths .get (end );
127125 return (new Graph .CostPathPair <Integer >(pair .getCost (), set ));
128126 }
129127 return null ;
0 commit comments