Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit c988148

Browse files
committedOct 7, 2024·
Refactor Dijkstra pseudo-code and function for readability and type safety
- Updated pseudo-code to reflect optimizations and variable naming improvements - Added type hints to the `dijkstra` function and variables for enhanced clarity - Introduced a `costs` dictionary to track minimum costs, avoiding redundant heap pushes - Adjusted line lengths to comply with style guidelines
1 parent 2d671df commit c988148

File tree

1 file changed

+49
-38
lines changed

1 file changed

+49
-38
lines changed
 

‎graphs/dijkstra.py

Lines changed: 49 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,28 @@
33
44
DIJKSTRA(graph G, start vertex s, destination vertex d):
55
6-
//all nodes initially unexplored
7-
8-
1 - let H = min heap data structure, initialized with 0 and s [here 0 indicates
9-
the distance from start vertex s]
10-
2 - while H is non-empty:
11-
3 - remove the first node and cost of H, call it U and cost
12-
4 - if U has been previously explored:
13-
5 - go to the while loop, line 2 //Once a node is explored there is no need
14-
to make it again
15-
6 - mark U as explored
16-
7 - if U is d:
17-
8 - return cost // total cost from start to destination vertex
18-
9 - for each edge(U, V): c=cost of edge(U,V) // for V in graph[U]
19-
10 - if V explored:
20-
11 - go to next V in line 9
21-
12 - total_cost = cost + c
22-
13 - add (total_cost,V) to H
6+
// all nodes initially unexplored
7+
8+
1 - let H = min heap data structure, initialized with (0, s)
9+
// 0 is the distance from start vertex s
10+
2 - let costs = dictionary to store minimum costs to reach each node,
11+
initialized with {s: 0}
12+
3 - while H is non-empty:
13+
4 - remove the first node and cost from H, call them U and cost
14+
5 - if U has been previously explored:
15+
6 - continue // skip further processing and go back to while loop, line 3
16+
7 - mark U as explored
17+
8 - if U is d:
18+
9 - return cost // total cost from start to destination vertex
19+
10 - for each neighbor V and edge cost c of U in G:
20+
11 - if V has been previously explored:
21+
12 - continue to next neighbor V in line 10
22+
13 - total_cost = cost + c
23+
14 - if total_cost is less than costs.get(V, ∞):
24+
15 - update costs[V] to total_cost
25+
16 - add (total_cost, V) to H
26+
27+
// At the end, if destination d is not reachable, return -1
2328
2429
You can think at cost as a distance where Dijkstra finds the shortest distance
2530
between vertices s and v in a graph G. The use of a min heap as H guarantees
@@ -34,7 +39,7 @@
3439
import heapq
3540

3641

37-
def dijkstra(graph, start, end):
42+
def dijkstra(graph: dict[str, list[tuple[str, int]]], start: str, end: str) -> int:
3843
"""Return the cost of the shortest path between vertices start and end.
3944
4045
>>> dijkstra(G, "E", "C")
@@ -44,31 +49,37 @@ def dijkstra(graph, start, end):
4449
>>> dijkstra(G3, "E", "F")
4550
3
4651
"""
52+
heap: list[tuple[int, str]] = [(0, start)] # (cost, node)
53+
visited: set[str] = set()
54+
costs: dict[str, int] = {start: 0} # Store minimum costs to reach each node
4755

48-
heap = [(0, start)] # cost from start node,end node
49-
visited = set()
5056
while heap:
51-
(cost, u) = heapq.heappop(heap)
57+
cost, u = heapq.heappop(heap)
5258
if u in visited:
5359
continue
5460
visited.add(u)
5561
if u == end:
5662
return cost
63+
5764
for v, c in graph[u]:
5865
if v in visited:
5966
continue
60-
next_item = cost + c
61-
heapq.heappush(heap, (next_item, v))
67+
next_cost = cost + c
68+
# Only push to heap if a cheaper path is found
69+
if next_cost < costs.get(v, float("inf")):
70+
costs[v] = next_cost
71+
heapq.heappush(heap, (next_cost, v))
72+
6273
return -1
6374

6475

6576
G = {
66-
"A": [["B", 2], ["C", 5]],
67-
"B": [["A", 2], ["D", 3], ["E", 1], ["F", 1]],
68-
"C": [["A", 5], ["F", 3]],
69-
"D": [["B", 3]],
70-
"E": [["B", 4], ["F", 3]],
71-
"F": [["C", 3], ["E", 3]],
77+
"A": [("B", 2), ("C", 5)],
78+
"B": [("A", 2), ("D", 3), ("E", 1), ("F", 1)],
79+
"C": [("A", 5), ("F", 3)],
80+
"D": [("B", 3)],
81+
"E": [("B", 4), ("F", 3)],
82+
"F": [("C", 3), ("E", 3)],
7283
}
7384

7485
r"""
@@ -80,10 +91,10 @@ def dijkstra(graph, start, end):
8091
----------------- 3 --------------------
8192
"""
8293
G2 = {
83-
"B": [["C", 1]],
84-
"C": [["D", 1]],
85-
"D": [["F", 1]],
86-
"E": [["B", 1], ["F", 3]],
94+
"B": [("C", 1)],
95+
"C": [("D", 1)],
96+
"D": [("F", 1)],
97+
"E": [("B", 1), ("F", 3)],
8798
"F": [],
8899
}
89100

@@ -96,12 +107,12 @@ def dijkstra(graph, start, end):
96107
-------- 2 ---------> G ------- 1 ------
97108
"""
98109
G3 = {
99-
"B": [["C", 1]],
100-
"C": [["D", 1]],
101-
"D": [["F", 1]],
102-
"E": [["B", 1], ["G", 2]],
110+
"B": [("C", 1)],
111+
"C": [("D", 1)],
112+
"D": [("F", 1)],
113+
"E": [("B", 1), ("G", 2)],
103114
"F": [],
104-
"G": [["F", 1]],
115+
"G": [("F", 1)],
105116
}
106117

107118
short_distance = dijkstra(G, "E", "C")

0 commit comments

Comments
 (0)
Please sign in to comment.