Skip to content

Commit 1d74c6e

Browse files
author
Farai Mugaviri
committed
Added Dijkstra's shortest path problem
1 parent e2a78d4 commit 1d74c6e

File tree

1 file changed

+85
-0
lines changed

1 file changed

+85
-0
lines changed

searches/dijkstra.py

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
"""Dijkstra's shortest path algorithm.
2+
3+
This module provides a simple Dijkstra implementation that works on a
4+
graph represented as an adjacency mapping: {node: [(neighbor, weight), ...], ...}.
5+
6+
Functions:
7+
- dijkstra(graph, source) -> (dist, prev)
8+
- shortest_path(prev, target) -> list
9+
10+
Doctests include a small example graph.
11+
"""
12+
from __future__ import annotations
13+
14+
import heapq
15+
from typing import Dict, Iterable, List, Tuple, Any
16+
17+
18+
def dijkstra(graph: Dict[Any, Iterable[Tuple[Any, float]]], source: Any) -> Tuple[Dict[Any, float], Dict[Any, Any]]:
19+
"""Compute shortest path distances from source to all reachable nodes.
20+
21+
Args:
22+
graph: adjacency mapping where graph[u] yields (v, weight) pairs.
23+
source: start node.
24+
25+
Returns:
26+
(dist, prev)
27+
- dist: mapping node -> distance (float). Unreachable nodes are absent.
28+
- prev: mapping node -> predecessor on shortest path (or None for source).
29+
30+
Example:
31+
>>> graph = {
32+
... 'A': [('B', 1), ('C', 4)],
33+
... 'B': [('C', 2), ('D', 5)],
34+
... 'C': [('D', 1)],
35+
... 'D': []
36+
... }
37+
>>> dist, prev = dijkstra(graph, 'A')
38+
>>> dist['D']
39+
4
40+
>>> shortest_path(prev, 'D')
41+
['A', 'B', 'C', 'D']
42+
"""
43+
dist: Dict[Any, float] = {}
44+
prev: Dict[Any, Any] = {}
45+
pq: List[Tuple[float, Any]] = [] # (distance, node)
46+
47+
heapq.heappush(pq, (0.0, source))
48+
dist[source] = 0.0
49+
prev[source] = None
50+
51+
while pq:
52+
d, u = heapq.heappop(pq)
53+
# Skip stale entries
54+
if d != dist.get(u, float('inf')):
55+
continue
56+
for v, w in graph.get(u, []):
57+
nd = d + float(w)
58+
if nd < dist.get(v, float('inf')):
59+
dist[v] = nd
60+
prev[v] = u
61+
heapq.heappush(pq, (nd, v))
62+
63+
return dist, prev
64+
65+
66+
def shortest_path(prev: Dict[Any, Any], target: Any) -> List[Any]:
67+
"""Reconstruct path from source to target using predecessor map.
68+
69+
If target is not in `prev`, returns an empty list.
70+
"""
71+
if target not in prev:
72+
return []
73+
path: List[Any] = []
74+
cur = target
75+
while cur is not None:
76+
path.append(cur)
77+
cur = prev.get(cur)
78+
path.reverse()
79+
return path
80+
81+
82+
if __name__ == "__main__":
83+
import doctest
84+
85+
doctest.testmod()

0 commit comments

Comments
 (0)