DFS works differently from BFS. Instead of moving level by level, it follows one path as far as it can go before backtracking. Think of it as diving deep down a trail, then returning to explore the others.
We can implement DFS in two ways:
- Recursive DFS, which uses the function call stack
- Iterative DFS, which uses an explicit stack
DFS is especially useful for
- Cycle detection
- Maze solving and puzzles
- Topological sorting
#Recursive DFS
def dfs_recursive(graph, node, visited=None):
if visited is None:
visited = set()
if node not in visited:
print(node, end=" ")
visited.add(node)
for neighbor in graph[node]:
dfs_recursive(graph, neighbor, visited)
graph = {
'A': ['B','C'],
'B': ['A','D','E'],
'C': ['A','F'],
'D': ['B'],
'E': ['B','F'],
'F': ['C','E']
}
dfs_recursive(graph, 'A')
visitedis a set that tracks nodes already processed so you don’t loop forever on cycles.- On each call, if
nodehasn’t been seen, it’s printed, marked visited, then the function recurses into each neighbor.
Traversal order:
A B D E F C
#Iterative DFS
def dfs_iterative(graph, start):
visited = set()
stack = [start]
while stack:
node = stack.pop()
if node not in visited:
print(node, end=" ")
visited.add(node)
stack.extend(reversed(graph[node]))
dfs_iterative(graph, 'A')
visitedtracks nodes you’ve already processed so you don’t loop on cycles.stackis LIFO (last in, first out) – youpop()the top node, process it, then push its neighbors.reversed(graph[node])pushes neighbors in reverse so they’re visited in the original left-to-right order (mimicking the usual recursive DFS).
Here’s the output:
A B D E F C