Dijkstra’s algorithm is commonly used to get the shortest path from a starting vertex to an end vertex on a graph with non-negative weights.
Two sets are maintained at each step: a set of explored nodes which have already been visited and a set of not-yet-visited nodes whose minimum distance from the start node may change at any time a better path is discovered. If an adjacency list to traverse the graph in \( O(V+E) \) is used together with a binary heap to track the minimum of the not-yet-explored set in \( O(\log{V}) \), the overall is \( O((E+V)\log{V}) \).
for every node V
costToReachNode[V] = +inf
costToReachNode[0] = 0 // Root node
heap = create a heap with the costToReachNode for all the nodes
while(heap is not empty)
node = getMinimumCostNode(heap)
if(costToReachNode[node] == +inf)
break; // No other node can be reached
for every edge from node
updateMinimumDistanceCosts(edge) // Updates if a better distance was found
The algorithm might seem similar to Prim’s algorithm for minimum spanning trees but there’s a substantial difference between the two: Prim is a classic greedy algorithm which explores new vertices and stores the minimum cost edge to reach one. Prim has no memory of the previous structure of the graph while Dijkstra’s keeps a sum of the distance spent to reach a vertex when comparing it with a new distance discovered. This memory property ensures that the optimal shortest path is always found. Many other pathfinding algorithms (notably A*) also build and expand on this principle.
The following code uses the same mutable binary heap structure used in the MST post to speed up the algorithm on the following graph
Output
Found shortest path from node 0 to node 4:
{3;4} with weight 8
{2;3} with weight 1
{1;2} with weight 7
{0;1} with weight 10