Graph traversal
Algorithms
Computer Science
Data Structures
Breadth-First Search

Good graph traversal algorithm

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

There is no single "best" graph traversal algorithm for every problem. The right choice depends on what you want from the traversal: reachability, shortest path in an unweighted graph, exhaustive search, topological processing, or weighted pathfinding.

Breadth-First Search for Layered Exploration

Breadth-first search, or BFS, explores the graph level by level. Starting from a source node, it visits all immediate neighbors before moving to nodes that are farther away.

That makes BFS the standard choice when you need the shortest path in an unweighted graph.

python
1from collections import deque
2
3
4def bfs(graph, start):
5    visited = {start}
6    queue = deque([start])
7    order = []
8
9    while queue:
10        node = queue.popleft()
11        order.append(node)
12
13        for neighbor in graph[node]:
14            if neighbor not in visited:
15                visited.add(neighbor)
16                queue.append(neighbor)
17
18    return order
19
20
21graph = {
22    "A": ["B", "C"],
23    "B": ["D"],
24    "C": ["E"],
25    "D": [],
26    "E": [],
27}
28
29print(bfs(graph, "A"))

BFS uses a queue and usually runs in O(V + E) time for a graph with V vertices and E edges.

Depth-First Search for Structure and Exhaustion

Depth-first search, or DFS, follows one path as far as possible before backtracking. It is a natural fit for recursive structure, cycle detection, topological sorting, and backtracking-style searches.

python
1def dfs(graph, start, visited=None, order=None):
2    if visited is None:
3        visited = set()
4    if order is None:
5        order = []
6
7    visited.add(start)
8    order.append(start)
9
10    for neighbor in graph[start]:
11        if neighbor not in visited:
12            dfs(graph, neighbor, visited, order)
13
14    return order
15
16
17print(dfs(graph, "A"))

DFS also runs in O(V + E) time, but it explores the graph in a very different order. That order can be useful when the search should dive into one branch deeply before considering alternatives.

Choosing Between BFS and DFS

Use BFS when:

  • edges are unweighted and you need the shortest path length
  • you care about distance in layers from a source
  • you want a level-order style traversal

Use DFS when:

  • you want to explore connected structure deeply
  • you are doing cycle detection or topological ordering
  • the problem looks like backtracking or path enumeration

That is why asking for a "good graph traversal algorithm" without context is slightly incomplete. The graph alone does not choose the algorithm; the goal does.

Weighted Graphs Need Something Else

If the graph edges have costs and you want the cheapest path, BFS is no longer enough. You need an algorithm such as Dijkstra's algorithm for non-negative weights or A* when you have a useful heuristic.

That is an important practical point. Many beginners reach for BFS out of habit and then get wrong answers on weighted graphs.

Representation Matters Too

Traversal performance also depends on how the graph is stored. An adjacency list is usually the best representation for sparse graphs because it lets you iterate over outgoing neighbors directly.

python
1graph = {
2    0: [1, 2],
3    1: [2],
4    2: [3],
5    3: [],
6}

For dense graphs, adjacency matrices can be acceptable, but they often make neighbor iteration more expensive because you scan whole rows.

Common Pitfalls

The biggest pitfall is choosing the traversal before clarifying the problem. If you need shortest paths in an unweighted graph, DFS is usually the wrong tool. If you need a cheap way to explore reachable structure, BFS may be unnecessary overhead.

Another issue is forgetting a visited set. Without it, traversals on cyclic graphs can loop forever or revisit large portions of the graph repeatedly.

Developers also sometimes use recursive DFS on very deep graphs and hit recursion limits. In those cases, an explicit stack-based DFS is safer.

Finally, remember that weighted shortest-path problems are not plain graph traversal problems anymore. They need algorithms that account for cost.

Summary

  • BFS is best for shortest paths in unweighted graphs and level-by-level exploration.
  • DFS is best for deep structural exploration, backtracking, and algorithms such as topological sorting.
  • Both BFS and DFS run in O(V + E) time with an adjacency-list representation.
  • There is no universally best traversal algorithm without a concrete goal.
  • For weighted shortest paths, use algorithms such as Dijkstra's instead of plain BFS or DFS.

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.