Breadth First Search
BFS
recursion
graph algorithms
recursive BFS

Performing Breadth First Search recursively

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

Introduction

Breadth-First Search (BFS) is a common graph traversal algorithm that explores nodes layer by layer, making it suitable for exploring the shortest path in unweighted graphs. While BFS is typically implemented using a queue due to its iterative nature, it is possible to perform a BFS traversal recursively with careful restructuring. This article explores the recursive approach to BFS, providing technical insight and examples.

Understanding BFS

In BFS, the starting node is explored first, followed by all its neighboring nodes at the present depth, before proceeding to nodes at the next depth level. It contrasts with Depth-First Search (DFS), which explores as far as possible down one branch before backtracking.

Key Properties of BFS

  • Time Complexity: O(V+E)O(V + E), where VV is the number of vertices and EE is the number of edges.
  • Space Complexity: O(V)O(V), due to the need to track visited nodes.
  • Shortest Path: Naturally finds the shortest path in an unweighted graph.

Recursive BFS Implementation

A traditional BFS uses a queue to maintain the frontier, i.e., the current layer of nodes being explored. The recursive approach to BFS uses a helper function to achieve a similar effect, managing the frontier layer by layer.

Recursive BFS Algorithm

  1. Base Step: Start by calling the BFS function with the root node, adding it to the visited set.
  2. Recursive Step: For each node in the current layer, explore its unvisited neighbors. Collect these neighbors and pass them to the next recursive call.
  3. Termination: The recursion terminates when there are no more nodes to explore.

Pseudo-code for Recursive BFS

Here's a simple pseudo-code illustration:

plaintext
1function recursiveBFS(currentLayer):
2  if currentLayer is empty:
3    return
4
5  nextLayer = []
6  for node in currentLayer:
7    for each neighbor in getNeighbors(node):
8      if neighbor is not in visited:
9        mark neighbor as visited
10        nextLayer.append(neighbor)
11
12  recursiveBFS(nextLayer)

Example

Consider the following graph represented as an adjacency list:

plaintext
1graph = {
2  'A': ['B', 'C'],
3  'B': ['A', 'D', 'E'],
4  'C': ['A', 'F'],
5  'D': ['B'],
6  'E': ['B', 'F'],
7  'F': ['C', 'E']
8}

Implementing recursive BFS on this graph starting from node 'A' would traverse the nodes as follows: A -> B -> C -> D -> E -> F.

python
1def recursive_bfs(graph, current_layer, visited):
2    if not current_layer:
3        return
4
5    next_layer = []
6    for node in current_layer:
7        for neighbor in graph[node]:
8            if neighbor not in visited:
9                visited.add(neighbor)
10                next_layer.append(neighbor)
11
12    recursive_bfs(graph, next_layer, visited)
13
14# Usage
15visited_set = set('A')
16recursive_bfs(graph, ['A'], visited_set)
17print(visited_set)

Key Considerations

While recursive BFS is an interesting variant, it is not commonly used due to the following concerns:

  • Call Stack Limitations: Recursive implementations are constrained by the maximum call stack size, making large graphs challenging.
  • Inefficiency: The overhead of recursive calls can lead to inefficiencies compared to the iterative method.
  • Clarity: Traditional iterative BFS is often more intuitive, especially as queue operations align naturally with BFS’s level-order exploration.

Summary Table

FeatureBFSRecursive BFS
Data StructureQueueImplicit Call Stack
Space ComplexityO(V)O(V)O(V+D)O(V + D) (D: max depth)
PerformanceEfficientLess Efficient
Suitability for Large GraphsYesLimited by stack depth
IntuitionEasierTrickier

Conclusion

Recursive BFS offers an alternative to the conventional graph traversal model and serves as an insightful academic exercise in converting iterative processes to recursive ones. However, in practical applications, especially involving large graphs, the traditional queue-based BFS remains the more effective solution due to its simplicity and efficiency in handling real-world constraints like memory and performance. Understanding both methods enables deeper insights into algorithm design and computational logic.


Related reading
Course
Intermediate
27 lessons
15 hours
DSA Fundamentals

Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

All Rights Reserved.