# Outline of Class 50: Dijkstra's Shortest Path Algorithm

Held: Monday, May 4, 1998

• Today is "evaluation day". You'll be given about twenty minutes to fill in the standard departmental evaluation form. I'll have a custom evaluation form ready later this week (one that we won't spend class time on).
• If you're wondering what is new about 152 this term: all the libraries and labs you did were newly written for this term. The outlines are about 60/40 old/new.
• The exams are now graded. I will turn them back after the evaluations are completed so as to avoid biasing the results. I've also prepared an answer key.

## Dijkstra's Algorithm

• A computer scientist named Dijkstra proposed an interesting strategy for finding the shortest path from A to B.
• He suggested that we can find the shortest path from A to B by finding the shortest path from A to all nodes in the graph. (Talk about overkill.)
• His algorithm is generally used with the "sum of weights" metric.
• It may also work with selected other metrics.
• His algorithm assumes that edge weights are nonnegative.
• We'll divide the graph into two parts:
• SP. The nodes whose shortest path we know. For these nodes, we'll store the distance to that node and the path to that node.
• Est. The nodes whose shortest path we don't know. For these nodes, we'll store the shortest known distance to that node (which may not be the shortest) and the corresponding path.
• Initially, Est contains all the nodes. The distance from A to itself is 0, and the distance from A to every other node is some distance greater than the largest distance in the graph.
• At each step, we'll move one node from Est to SP. After doing so, we'll update the estimated costs of all of its neighbors.
• Which node to we move? Node s, The one with the smallest estimated distance.
• Why is this safe? Because the only way to reduce that distance would be to pick another node, t from Est and have a path from that node to s such that A to t to s has smaller distance than our current estimate of the distance form A to s. But that's not possible, since the cost function is non-decreasing, and we already know that the cost from A to t is at least as big as the cost from A to s.
• Note that instead of storing the path, we can simply store the previous node in the path.
• Dijkstra's algorithm is an example of a greedy algorithm: at each step in the algorithm, we pick a "best" node

### An Example

• Here's a sample graph to consider. I've used an undirected graph because the algorithm works equally well for undirected graphs and they're easier to draw.
```    G
|
3|
| 1   4   1   9
A---B---C---D---E
|   |   |       |
9|  2|  0|       |
|   |   |       |
+---F---+       |
|      6    |
+-----------+
```
• What is the shortest path from A to E? It may be hard to see at first (not too hard, but nontrivial).
• Let's see what the algorithm tells us.
• Initially,
• SP = { }
• Est = { A:(0,empty) B:(100,?) C:(100,?) D:(100,?) E:(100,?) F:(100,?) G:(100,?) }
• The smallest distance in that graph is the distance to A, so we
• Move A to SP
• Update the distances to all of its neighbors (B, F, and G which now have actual paths and distances)
• We now have the following information
• SP = { A:(0,empty) }
• Est = { B:(1,A) G:(3,A) F:(9,A) C:(100,?) D:(100,?) E:(100,?) }
• We move B to SP and update its neighbors. We now know a path to C and a better path to F (A->B->F has cost 1 + 2 = 3).
• SP = { A:(0,empty) B:(1,A) }
• Est = { F:(3,B) G:(3,A) C:(5,B) D:(100,?) E:(100,?) }
• We could then move F or G to SP. Let's say that we move F. We now know a shorter path to C (A->B->F->C has cost 3, A->B->C had cost 5) and a path to E.
• SP = { A:(0,empty) B:(1,A) F:(3,B) }
• Est = { G:(3,A) C:(3,F) E:(9,F) D:(100,?) }
• We can then move G or C to SP. Let's say that we move G. G has no neighbors, so there are no other changes.
• SP = { A:(0,empty) B:(1,A) F:(3,B) G:(3,A) }
• Est = { C:(3,F) E:(9,F) D:(100,?) }
• Next we move C. We can then update the distance to D.
• SP = { A:(0,empty) B:(1,A) F:(3,B) G:(3,A) C:(3,F) }
• Est = { D:(4,C) E:(9,F) }
• We then move D. Note that even though there is an edge from D to E, it doesn't give us any better path, so we don't change the entry for E.
• SP = { A:(0,empty) B:(1,A) F:(3,B) G:(3,A) C:(3,F) D:(4,C) }
• Est = { E:(9,F) }
• We move E and we're done
• SP = { A:(0,empty) B:(1,A) F:(3,B) G:(3,A) C:(3,F) D:(4,C) E:(9,F) }
• Est = { }
• What's the shortest path from A to E? It has cost 9 and is the reverse of (E-F-B-A). How did I get that path? I read it off from the second elements of SP.

### Sample Code

• Let's turn this into Java code (or something resembling Java code).
• Note that we need any easy way to handle the "sets" of Node/cost (and Node/cost/previous). For now, we'll use dictionaries.
```/**
* Compute the shortest paths from a node to every other node in
* the graph.
*
* pre: The graph is initialized.
* pre: The root is in the graph.
* pre: The graph is nonempty.
* post: An array of distance/prevnode pairs is returned.
* post: The underlying graph is unaffected.
*/
Dictionary shortestPaths(Node root) {
Dictionary SP;  // The cost/previous pairs
Dictionary Est; // Estimated  "        "
Node next;      // The next node to add to SP
Node neighbor;  // Neighbors of next;
int distance;	  // The distance to the current node.
int newdist;    // Potential new distance to neighbor

// Initialze "sets".  In a real program, we'd need
// to choose a particular implementation of Dictionary.
SP = new Dictionary();
Est = new Dictionary();

// Initialize Est.
Est.put(root, new Pair(0,null));
Iterator node = allNodesInCurrentGraph();
while (nodes.hasMoreElements()) {
next = nodes.nextElement();
if (!next.equals(root)) {
}
} // for

// Remove nodes from Est until it is empty.
while(!Est.empty()) {
// The next line is not legal Java, but its meaning
// should be clear.
(next,distance) = smallest(Est);
if (distance == MAXPATH+1) {
// Whatever you want to do if there is no path to some nodes
}
Iterator neigborhs = next.neighbors();
while (neighbors.hasMoreElements) {
// Get a neighbor
neighbor = neighbors.nextElement();
// Compute the distance to that neighbor if we pass
// through the current node.
newdist = distance + weight(next,neighbor);
// If that's better than the best known distance, update
// the best known distance
if (newdist < Est.get(neighbor).distance) {
Est.put(neighbor, new Pair(newdist, next));
} // If we've found a better path
} // for each neighbor
} // while there are nodes left in Est.

// Done
return SP:
} // shortestPaths
```

### Running Time

• What's the running time of this algorithm?
• During initialization, we visit each node once, which is O(n).
• In the main loop, we remove each node from Est once, so there are O(n) repetitions of the main loop.
• We look at each edge twice (one for each node connected to the edge), so the "update distances" part takes O(m) across the whole algorithm.
• How long does it take to find the smallest distance in Est? For the structures we've learned, O(n).
• We've find the smallest distance O(n) times.
• So, the running time is O(n^2 + m).
• Since m is O(n^2), the running time is O(n^2).
• That's a significant improvement over the previous algorithm.
• Can we improve it more? In particular, can we speed up the determination of the smallest distance in Est?
• We might consider using a Heap, since we're doing a lot of removeSmallest.
• However, we do change priorities of objects, and Heaps aren't designed to easily support that operation. (How might you support a `changePriority` method?)

On to Graphs, Concluded
Back to Reachability and Shortest Path Algorithms
Outlines: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
Current position in syllabus

Disclaimer Often, these pages were created "on the fly" with little, if any, proofreading. Any or all of the information on the pages may be incorrect. Please contact me if you notice errors.

Source text last modified Tue Jan 12 11:52:32 1999.

This page generated on Mon Jan 25 09:50:10 1999 by SiteWeaver. Validate this page.

Contact our webmaster at rebelsky@math.grin.edu