Preamble
DFS is the backbone of many easy–medium graph problems (topic plan algorithms track): connectivity, cycle detection with coloring, exhaustive search. Here are recursive and stack-based variants on an adjacency list—same algorithm, different stack discipline.
Adjacency list DFS
def dfs_rec(graph, start, visited=None):
if visited is None:
visited = set()
visited.add(start)
for nbr in graph.get(start, ()):
if nbr not in visited:
dfs_rec(graph, nbr, visited)
return visited
def dfs_iter(graph, start):
seen, stack = set(), [start]
while stack:
v = stack.pop()
if v in seen:
continue
seen.add(v)
stack.extend(graph.get(v, ()))
return seen
Order may differ between versions—document whether pre-order matters for your problem.
Debugging and stack depth
Recursion reads cleanly for small graphs; iterative DFS avoids RecursionError on deep chains. Single-step debugging is often easier on the explicit stack variant.
Conclusion
Time O(V + E), space O(V) for visited plus stack/recursion. Pick the version you can explain under pressure. Breadth-First Search and Shortest Path Layers in Python covers BFS and deque.