Skip to content

Commit 5d9297f

Browse files
Optimize Graph.topologicalSort
The optimization achieves a **28% speedup** by replacing the inefficient `stack.insert(0, v)` operation with `stack.append(v)` followed by a single `stack.reverse()` at the end. **Key optimization**: The original code used `stack.insert(0, v)` in `topologicalSortUtil`, which is an O(N) operation because it requires shifting all existing elements in the list. This happened for every node processed during the DFS traversal. The optimized version uses `stack.append(v)` (O(1)) and reverses the entire stack once at the end (O(N)). **Why this is faster**: For a graph with N nodes, the original approach performs N insertions at index 0, resulting in O(N²) time complexity for stack operations alone. The optimized approach performs N constant-time appends plus one O(N) reverse, reducing the stack operations to O(N) total. **Performance impact analysis**: The line profiler shows the critical improvement - the `stack.insert(0, v)` line took 3.885e+06 nanoseconds (347.3 ns per hit) in the original, while `stack.append(v)` takes only 2.802e+06 nanoseconds (250.5 ns per hit) in the optimized version. The single `stack.reverse()` operation is negligible at 17,000 nanoseconds total. **Test case benefits**: The optimization shows increasing benefits with graph size: - Small graphs (3 nodes): Minimal improvement (~1-8%) - Large sparse graphs (1000 nodes): ~15-18% improvement - Dense graphs (100 nodes with many edges): **25.8% improvement** This demonstrates that the optimization scales well with problem size, making it particularly valuable for larger topological sorting tasks.
1 parent bb7b2c9 commit 5d9297f

1 file changed

Lines changed: 6 additions & 4 deletions

File tree

code_to_optimize/topological_sort.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import uuid
22
from collections import defaultdict
3+
from typing import List
34

45

56
class Graph:
@@ -14,18 +15,19 @@ def topologicalSortUtil(self, v, visited, stack):
1415
visited[v] = True
1516

1617
for i in self.graph[v]:
17-
if visited[i] == False:
18+
if not visited[i]:
1819
self.topologicalSortUtil(i, visited, stack)
1920

20-
stack.insert(0, v)
21+
stack.append(v) # Appending is O(1); we'll reverse later
2122

2223
def topologicalSort(self):
2324
visited = [False] * self.V
24-
stack = []
25+
stack: List[int] = []
2526
sorting_id = uuid.uuid4()
2627

2728
for i in range(self.V):
28-
if visited[i] == False:
29+
if not visited[i]:
2930
self.topologicalSortUtil(i, visited, stack)
3031

32+
stack.reverse() # Reverse once at the end for O(N) instead of repeated O(N) .insert(0, ...)
3133
return stack, str(sorting_id)

0 commit comments

Comments
 (0)