liveBook · Manning

Dijkstra's algorithm

As explained in Advanced Algorithms and Data Structures

Dijkstra's algorithm computes shortest paths from a source in a graph with nonnegative edge weights by repeatedly selecting the unsettled vertex with minimum tentative distance.

Dijkstra's algorithm finds minimum-weight paths from a source vertex through a weighted graph. It suits irregular maps where distance cannot be approximated by counting edges, provided every edge has nonnegative weight. section 14.0 section 14.4

The algorithm proceeds by maintaining tentative distances and a frontier ordered by distance:

  • Initialize the source distance to zero, every other distance to infinity, and each predecessor to null. section 14.4.2
  • Insert the source into a min-priority queue, repeatedly extract the closest discovered vertex, and optionally stop when it satisfies the goal condition. section 14.4.1 section 14.4.2
  • Relax each outgoing edge: replace a neighbor's tentative distance when the route through the current vertex is shorter, then update its predecessor and queue priority. section 14.4.2 section 14.4.3
  • Reconstruct the route by following predecessor links from the destination back to the source. section 14.4.2 section 14.4.4

Choosing distance over edge count

In a weighted graph, a two-edge route from v1 through v3 to v2 can weigh 8, while a three-edge route through v5 can weigh 5. Dijkstra's algorithm first records 8, then lowers the tentative distance to 5 when the better route is discovered. section 14.4.3

Listing 14.6 Dijkstra’s algorithm
function dijkstra(graph, start, isGoal)                   #1
  queue ← new PriorityQueue()                             #2
  queue.insert(start, 0)                                  #3
  distances[v] ← inf (∀ v ϵ graph | v <> start)           #4
  parents[v] ← null (∀ v ϵ graph)                         #5
  distances[start] ← 0                                    #6
  while not queue.empty() do                              #7
    v ← queue.top()                                       #8
    if isGoal(v) then                                     #9
      return (v, parents)
    else
      for e in graph.adjacencyList[v] do                  #10
        u ← e.dest
        if distances[u] > distances[v] + e.weight then    #11
          distances[u] ← e.weight + distances[v]          #12
          parents[u] ← v
          queue.update(u, distances[u])
  return (null, parents)                                  #13

Use the implementation listing to trace initialization, priority-queue processing, relaxation, and predecessor updates. section 14.4.2

A plain queue is insufficient because a path with more edges can have lower total weight. With an array priority queue, running time is O(|E|*|V|); with a heap it is O(|E|*log(|V|)); with a Fibonacci heap it is O(|V|*log(|V|)+|E|) amortized. Negative-weight edges invalidate the greedy assumption. section 14.4.3 section 14.4.4

How Advanced Algorithms and Data Structures covers it

How deep it goes
Develops weighted-path intuition, pseudocode operations, reconstruction, priority-queue trade-offs, and the nonnegative-weight limitation.
Examples
Uses irregular city maps, delivery routes, and competing paths whose edge counts and total weights favor different choices.
What it assumes
Assumes graph representations and familiarity with BFS, while extending edge-count search to weighted distances.
What you can do after
Build it from scratch using a priority queue, tentative distances, predecessor links, and edge relaxation.
How it connects
Extends BFS for weighted paths and contrasts with A*, while relying on graphs, adjacency lists, and priority queues.

Also explained in

Compare how 5 books explain Dijkstra's algorithm →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Advanced Algorithms and Data Structures. The section links point to the parts of the book it draws on.