Skip to main content
Binary Trees & Graphs
CHAPTER 24 Beginner

Dijkstra’s Algorithm

Updated: May 17, 2026
10 min read

# CHAPTER 24

Dijkstra’s Algorithm

1. Introduction

In 1956, a computer scientist named Edsger W. Dijkstra was having coffee at a cafe in Amsterdam. He was pondering a simple question: "What is the shortest way to travel from Rotterdam to Groningen?" In just 20 minutes, without a computer, he invented an algorithm that would eventually power Google Maps, IP Routing, and global logistics networking. Dijkstra's Algorithm is the undisputed king of Weighted Shortest Path routing. By weaponizing a Min-Heap (Priority Queue), it aggressively and greedily explores only the absolute cheapest paths, guaranteeing flawless mathematical routing speeds.

2. Learning Objectives

By the end of this chapter, you will be able to:
  • Define the "Greedy" logic driving Dijkstra's Algorithm.
  • Understand the integration of the Min-Heap (Priority Queue) to extract the cheapest node.
  • Execute Edge Relaxation sequentially across a weighted matrix.
  • Code a production-ready Dijkstra implementation in Python.

3. The Core Concept (Greedy Min-Heap)

If you run BFS on a graph, it checks all neighbors blindly. Dijkstra's Algorithm is smarter. It uses a Min-Heap Priority Queue. Instead of checking nodes randomly, the Priority Queue strictly orders all available nodes by their Current Total Cost. The algorithm always pops the absolute *cheapest* node available from the queue and explores its neighbors. Because it constantly attacks the cheapest paths first, it discovers the optimal route exponentially faster.

The Golden Rule: Once Dijkstra pops a Node from the Priority Queue and formally processes it, it permanently locks that node. It assumes it has found the absolute mathematical Shortest Path to that node and will *never* evaluate it again. (This is why it fails on Negative Weights!).

4. Step-by-Step Execution

We have an Array tracking Distances (initialized to Infinity). We have a Min-Heap tracking (Cost, NodeID).

The Graph:

  • A -> B (Weight 5)
  • A -> C (Weight 10)
  • B -> C (Weight 2)

The Goal: Shortest path from A to C.

  1. 1. Initialize: Distance[A] = 0. All others Infinity. Push (0, A) to Min-Heap.
  1. 2. Pop Min-Heap: We get A. Cost is 0.
  1. 3. Evaluate Neighbors of A:
  • Neighbor B: Path cost is $0 + 5 = 5$. Is $5 < \text{Infinity}$? Yes! Relax Edge. Distance[B] = 5. Push (5, B) to Heap.
  • Neighbor C: Path cost is $0 + 10 = 10$. Is $10 < \text{Infinity}$? Yes! Relax Edge. Distance[C] = 10. Push (10, C) to Heap.
  1. 4. Pop Min-Heap: The Heap contains (5, B) and (10, C). The absolute cheapest is (5, B). Pop B!
  1. 5. Evaluate Neighbors of B:
  • Neighbor C: Path cost to B is $5$. Edge from B to C is $2$. Total cost = $5 + 2 = 7$.
  • Relaxation Check: Is $7 < \text{Distance}[C]$ (which is currently 10)? YES! We found a shortcut! Overwrite Distance[C] = 7. Push (7, C) to Heap.
  1. 6. Pop Min-Heap: We pop (7, C). Target reached. Minimum path is exactly 7!

5. Code Implementation (Python)

Python's heapq module provides a native $O(\log N)$ Min-Heap!
python
123456789101112131415161718192021222324252627282930313233343536373839
import heapq

def dijkstra(graph, start_node):
    # Initialize distances to Infinity
    distances = {node: float(&#039;inf') for node in graph}
    distances[start_node] = 0
    
    # Priority Queue: stores tuples of (Cumulative_Cost, Node)
    pq = [(0, start_node)]
    
    while len(pq) > 0:
        # Pop the absolute cheapest node!
        current_distance, current_node = heapq.heappop(pq)
        
        # Optimization: If we found a cheaper path earlier, ignore this bloated frame
        if current_distance > distances[current_node]:
            continue
            
        # Explore neighbors
        for neighbor, weight in graph[current_node]:
            distance = current_distance + weight
            
            # Edge Relaxation!
            if distance < distances[neighbor]:
                distances[neighbor] = distance # Overwrite with cheaper cost
                heapq.heappush(pq, (distance, neighbor)) # Push to Min-Heap
                
    return distances

# Adjacency List: {Node: [(Neighbor, Weight)]}
graph = {
    &#039;A': [('B', 5), ('C', 10)],
    &#039;B': [('C', 2), ('D', 8)],
    &#039;C': [('D', 1)],
    &#039;D': []
}

print(dijkstra(graph, &#039;A'))
# Output: {'A': 0, 'B': 5, 'C': 7, 'D': 8}

6. Complexity Analysis

  • Time Complexity: $O((V + E) \log V)$. Evaluating every edge takes $E$. Extracting and pushing to the Min-Heap takes $\log V$. The combination ensures lightning-fast execution even on dense networks.
  • Space Complexity: $O(V + E)$ to store the Graph, plus $O(V)$ for the Distance Array and the Priority Queue.

7. The Negative Weight Fatal Flaw

If you have a Negative Edge (e.g., passing a toll booth that *pays* you $50), Dijkstra will completely collapse. Because Dijkstra is "Greedy," once it extracts a node from the Priority Queue, it marks it as permanently finished. If a negative edge deep in the graph suddenly makes an old path cheaper, Dijkstra refuses to look backward and fix it. (You must use the slower Bellman-Ford Algorithm instead).

8. Common Mistakes

  • Using a standard Queue: If you use a standard FIFO collections.deque instead of a heapq, you have destroyed the entire algorithm. It degrades into a horrific, brute-force BFS that wastes massive CPU cycles evaluating expensive paths blindly.

9. Exercises

  1. 1. Trace Dijkstra's algorithm on the Python graph provided above to find the path to Node D. Why does the algorithm choose the path through C instead of directly from B?
  1. 2. Theoretically explain why Dijkstra's algorithm processes unweighted graphs perfectly, but is considered overkill and inefficient compared to standard BFS.

10. MCQs with Answers

Question 1

What core architectural upgrade radically distinguishes Dijkstra's Algorithm from a standard, unweighted Graph BFS traversal?

Question 2

When Dijkstra's engine extracts a localized Node from the Min-Heap Priority Queue, what algorithmic "Greedy" assumption is rigidly locked into place?

Question 3

To mathematically trigger an "Edge Relaxation" event within the Dijkstra localized for loop, what exact Boolean logic constraint must evaluate to True?

Question 4

What is the explicit programmatic penalty resulting from executing Dijkstra’s logic utilizing a standard List and calling a generic .sort() function instead of deploying a formal Min-Heap?

Question 5

When initializing the foundational Dijkstra sequence, what numerical integer is strictly populated into the baseline origin Root node's tracker slot?

Question 6

If a specific graph intersection incorporates a "Negative Edge Weight" (-50 Cost), what catastrophic algorithmic failure does Dijkstra endure?

Question 7

What defines the rigorously proven Asymptotic Time Complexity limit for Dijkstra’s Algorithm executing upon a heavily saturated topological matrix?

Question 8

What specialized algorithmic engine is formally mandated to securely calculate Weighted Shortest Paths across matrices heavily polluted with Negative Edge anomalies?

Question 9

If you deploy Dijkstra’s logic to navigate a completely *Unweighted* networking array (where all connections inherently evaluate to a uniform weight of $1$), what is the architectural reality?

Q10. True or False: In a massive, heavily connected graph, Dijkstra's algorithm perfectly guarantees that the overarching global Min-Heap array size will never technically exceed the total integer quantity of $V$ (Vertices). a) True. Heaps physically cannot exceed array node constraints. b) False. Without ultra-strict programmatic caching filters, an inefficient Dijkstra implementation will blindly continuously push redundant (Cost, Target) tuples into the Heap array every single time an Edge Relaxation executes, causing the Heap geometry to vastly eclipse $V$ limit bounds. Answer: b) False. Without ultra-strict programmatic caching filters, an inefficient Dijkstra...

11. Interview Preparation

Top Interview Questions:
  • *Algorithmic Debugging:* "In the Python code, there is a line: if current_distance > distances[current_node]: continue. Why is this optimization absolutely critical?" *(Answer: Because Python's heapq does not support $O(\log N)$ dynamic internal value updating! When an Edge Relaxation occurs, we just push a duplicate tuple with the newer, cheaper price into the heap. When the old, expensive, obsolete tuple eventually pops, that if statement catches it and instantly discards it, preventing catastrophic duplicate processing!)*

12. Summary

Dijkstra's Algorithm proves the dominance of the Min-Heap. By continuously attacking the cheapest available geometric frontier, the algorithm systematically crushes network graphs, executing massive relational pathfinding calculations in seconds. Understanding its greedy limits and optimization traps elevates a developer into a true Systems Architect.

13. Next Chapter Recommendation

Dijkstra finds the fastest way to get from A to Z. But what if you are a city planner? You don't care about A to Z. You need to pave a road connecting *every single city* in the state, using the absolute minimum amount of asphalt possible. In Chapter 25: Minimum Spanning Trees, we abandon Point-A-to-Point-B routing and connect the entire universe utilizing Prim's and Kruskal's algorithms.

Finish this Chapter

Save your progress on your learning path and prepare for coding interview challenges.

Discussion

Join the discussion

Log in or create a free account to participate.

Sort: ·