2 of 2
Write a function dijkstra(graph, start) that finds the shortest distance from start to every other node in a weighted, undirected graph.
The graph is given as an adjacency list where graph[node] is a list of (neighbor, weight) tuples.
Return a dictionary mapping each node to its shortest distance from start.
graph = { "A": [("B", 4), ("C", 2)], "B": [("A", 4), ("C", 1), ("D", 5)], "C": [("A", 2), ("B", 1), ("D", 8), ("E", 10)], "D": [("B", 5), ("C", 8), ("E", 2), ("F", 6)], "E": [("C", 10), ("D", 2), ("F", 3)], "F": [("D", 6), ("E", 3)], } print(dijkstra(graph, "A")) # {"A": 0, "B": 3, "C": 2, "D": 8, "E": 10, "F": 13}
This is the Classic Graph from the animation β run it first to see Dijkstra's step by step.
| Complexity | |
|---|---|
| Time | O((V + E) log V) |
| Space | O(V + E) |
Where V is the number of nodes and E is the number of edges.
dist[start] = 0, all others = float("inf")[(0, start)]u with the smallest tentative distanceu is already visited, skip itu as visited (its distance is now final)v with edge weight w:
dist[u] + w < dist[v], update dist[v] and push (dist[v], v) to the heapdistimport heapq def dijkstra(graph, start): # Your code here pass # Test your function: graph = { "A": [("B", 4), ("C", 2)], "B": [("A", 4), ("C", 1), ("D", 5)], "C": [("A", 2), ("B", 1), ("D", 8), ("E", 10)], "D": [("B", 5), ("C", 8), ("E", 2), ("F", 6)], "E": [("C", 10), ("D", 2), ("F", 3)], "F": [("D", 6), ("E", 3)], } result = dijkstra(graph, "A") print(result) # Expected: {"A": 0, "B": 3, "C": 2, "D": 8, "E": 10, "F": 13} print(result["A"]) # 0 print(result["B"]) # 3 print(result["C"]) # 2 print(result["D"]) # 8 print(result["E"]) # 10 print(result["F"]) # 13
Set all distances to infinity first, then set the start to zero:
dist = {node: float("inf") for node in graph} dist[start] = 0
Python's heapq is a min-heap. Push (distance, node) tuples so the smallest distance is always popped first:
heap = [(0, start)] visited = set()
while heap: curr_dist, u = heapq.heappop(heap) if u in visited: continue visited.add(u) for neighbor, weight in graph[u]: # relax the edge ...
Check if going through u gives a shorter path to neighbor:
new_dist = curr_dist + weight if new_dist < dist[neighbor]: dist[neighbor] = new_dist heapq.heappush(heap, (new_dist, neighbor))
import heapq def dijkstra(graph, start): dist = {node: float("inf") for node in graph} dist[start] = 0 heap = [(0, start)] visited = set() while heap: curr_dist, u = heapq.heappop(heap) if u in visited: continue visited.add(u) for neighbor, weight in graph[u]: new_dist = curr_dist + weight if new_dist < dist[neighbor]: dist[neighbor] = new_dist heapq.heappush(heap, (new_dist, neighbor)) return dist
How it works:
dist[start] = 0, everything else starts at infinityif u in visited: continue check skips them