advanced9 min read·Updated October 2, 2026
Dijkstra's Shortest Path Explained: Tracing Distances in 4 Nodes
Master Dijkstra's shortest path with a complete step-by-step walkthrough of the 0-1-2-3 graph. Build mental models, trace greedy wavefronts, and avoid pitfalls.
By Learnisim AI·Published October 2, 2026
LEARNING ARCSetup → Model in the example → Full trace → Twist → Edge cases → Apply
PREREQUISITES
- Basic graph terminology (nodes, directed/undirected edges)
- Priority queues / min-heaps
- Greedy algorithm intuition
Why
Why Dijkstra's Shortest Path Exists: Routing Through Complexity
Phase 1: The Routing Dilemma
Imagine you are building a navigation system or routing packets across a network, and you need to get from node 0 to node 3. You are given a map with positive edge weights: a path from costs 1, costs 4, costs 1, costs 7, and costs 1. Without a systematic method, how do you know whether to take the seemingly direct route or a longer-looking sequence of smaller hops?
If you just explore blindly or pick the single cheapest local step at every turn, you can easily fall into costly traps. For instance, jumping straight from 0 to 2 costs 4, while routing through node 1 first costs to reach node 2. Greedy local choices or brute-force permutations quickly explode in complexity as networks grow from four nodes to thousands.
We need an algorithm that guarantees we find the absolute minimum cost to reach node 3 (and every other node) without wasting time checking redundant, suboptimal paths.
Model
The Greedy Wavefront: Modeling Dijkstra's Search
Phase 2: The Core Mental Model
To understand Dijkstra's shortest path explained, imagine dropping a drop of water into a network of pipes where pipe lengths represent our edge weights. The water flows outward, hitting the nearest junctions first. In graph theory, we mimic this physical wavefront using a priority queue (or min-heap) that always extracts the node with the currently smallest known distance from our start node 0.
In our working example, we have nodes and directed edges with weights: (cost 1), (cost 4), (cost 1), (cost 7), and (cost 1). Our start node is 0. Instead of guessing whether path or path is cheaper, our model maintains two central structures:
1. A distance array (
dist), initialized to infinity for all nodes except start (0), representing our upper bound for the shortest distance to each node.2.A min-heap tracking candidates to explore next, ordered by their tentative distance.
As the algorithm runs, whenever we visit the closest unvisited node, we relax its neighbors—meaning we check if routing through the current node offers a strictly shorter path than previously recorded. If it does, we update our distance array and push the updated cost into our heap.
Worked example
Tracing Dijkstra's Algorithm Step by Step on a Four-Node Graph
Phase 3: Worked Example
To see the wavefront model in action, let us trace our locked example: four nodes with directed nonnegative edges (weight 1), (weight 4), (weight 1), (weight 7), and (weight 1). We want to find the shortest path from start node 0 to target node 3.
Given:
- Nodes:
- Edges and weights:
- Distance array (initialized to , except
- Priority queue (storing tuples of
- Nodes:
- Edges and weights:
•Start node: 0
- Distance array (initialized to , except
dist[0] = 0): dist = [0, inf, inf, inf]- Priority queue (storing tuples of
(distance, node)): pq = [(0, 0)]Steps:
1. Pop
- Node 1: tentative distance = . Since (), update and push
- Node 2: tentative distance = . Since (), update and push
- State:
1. Pop
(0, 0) from pq:•Current node is 0 with distance 0.
•Examine neighbors of 0:
- Node 1: tentative distance = . Since (), update and push
(1, 1) to pq.- Node 2: tentative distance = . Since (), update and push
(4, 2) to pq.- State:
dist = [0, 1, 4, inf], pq = [(1, 1), (4, 2)]2. Pop
- Node 2: tentative distance = . Since (4), update and push
- Node 3: tentative distance = . Since (), update and push
- State:
(1, 1) from pq:•Current node is 1 with distance 1.
•Examine neighbors of 1:
- Node 2: tentative distance = . Since (4), update and push
(2, 2) to pq.- Node 3: tentative distance = . Since (), update and push
(8, 3) to pq.- State:
dist = [0, 1, 2, 8], pq = [(2, 2), (4, 2), (8, 3)] (Note the duplicate entry for node 2 with an older, larger distance).3. Pop
- Since this popped distance (2) matches our current , we process its neighbors. (If it were larger than
- Node 3: tentative distance = . Since (8), update and push
- State:
(2, 2) from pq:•Current node is 2 with distance 2.
- Since this popped distance (2) matches our current , we process its neighbors. (If it were larger than
dist[2]—like our upcoming stale (4, 2)—we would skip it). Examine neighbors of 2:- Node 3: tentative distance = . Since (8), update and push
(3, 3) to pq.- State:
dist = [0, 1, 2, 3], pq = [(3, 3), (4, 2), (8, 3)]4.Pop remaining entries:
- Pop
(3, 3): Node 3 is reached with optimal distance 3. It has no outgoing edges in our problem statement.- Pop
(4, 2): Stale entry (4 > dist[2] which is 2), so we skip it.- Pop
(8, 3): Stale entry (8 > dist[3] which is 3), so we skip it.Result:
- Final distance array:
- The shortest path to node 3 is with a total cost of 3, successfully bypassing the more expensive direct route (cost 8).
- Final distance array:
dist = [0, 1, 2, 3]- The shortest path to node 3 is with a total cost of 3, successfully bypassing the more expensive direct route (cost 8).
Practice
Predicting Wavefront Evolution on the 0-1-2-3 Network
Phase 4: Practice
Now that you have traced the full execution from node 0 to node 3, let us test your understanding of intermediate wavefront states. Recall our network configuration: edges are (cost 1), (cost 4), (cost 1), (cost 7), and (cost 1). We start at node 0 with
best = [0, inf, inf, inf].Imagine you have just popped node 0, relaxed its neighbors (nodes 1 and 2), and then popped node 1 from your priority queue. At the exact moment node 1 is popped and its outgoing edges are relaxed, what are the contents of the tentative distance array
best and the newly pushed entries in the priority queue before any stale elements are popped?Apply
Transferring Dijkstra's Logic: Navigating Dynamic Edge Mutations
Phase 5: Transfer
We have successfully tracked our wavefront across the locked example , settling final distances via the min-heap to find the optimal cost of 3. But real-world systems are rarely static. What happens when we reuse this exact algorithmic template on perturbed network topographies?
Consider our original graph—edges (1), (4), (1), (7), and (1)—modified in two distinct ways:
1.Unreachable node addition: Node 3 is completely disconnected by removing incoming edges from node 1 and node 2.
2.Zero-weight edge injection: A new direct edge from node 2 to node 3 with weight 0 is introduced.
Recall that our core invariant relies on non-negative edge weights to guarantee that the first time we pop a node from the priority queue, its distance is final. When applying this to our mutated variants, we must verify how the wavefront reacts to infinite bounds and zero-cost transitions.
In the first mutation, node 3 retains its initialization value of infinity because no relaxed path can reach it, cleanly signaling unreachability without breaking the algorithm. In the second mutation, the zero-weight edge allows instantaneous cost-free traversal, updating node 3's distance without violating the greedy assumption since .
FAQ
Why does the path 0-1-2-3 beat 0-1-3 in the worked example?
In the 4-node network, edge 1-3 costs 7, making path 0-1-3 cost 8. However, routing through node 2 via edges 0-1 (1), 1-2 (1), and 2-3 (1) yields a total cost of 3, demonstrating how greedy relaxation finds the true minimum.
Why does Dijkstra's algorithm fail with negative edge weights?
Dijkstra's algorithm relies on the greedy assumption that once a node's shortest distance is finalized, it can never be improved. Negative edges can invalidate this by offering a cheaper path later, requiring algorithms like Bellman-Ford instead.
What is the time complexity of Dijkstra's algorithm using a min-heap?
Using a binary min-heap, the time complexity is O((V + E) log V), where V is the number of vertices and E is the number of edges, because each vertex and edge insertion/extraction involves heap operations.