How do we systematically visit every node in a graph, and when do we use breadth-first versus depth-first search?
Implement and trace breadth-first and depth-first traversal of a graph, and contrast the two strategies and their applications
A focused answer to the H2 Computing outcome on graph traversal. Breadth-first search with a queue and depth-first search with a stack or recursion, tracing each on a graph, and choosing between them for shortest paths and exploration.
Reviewed by: AI editorial process; not yet individually human-reviewed
Have a quick question? Jump to the Q&A page
Jump to a section
What this dot point is asking
SEAB wants you to implement and trace breadth-first search (BFS) and depth-first search (DFS) on a graph, and to contrast the two strategies and where each is used. The central idea is that both visit every reachable node exactly once, but BFS explores level by level using a queue, while DFS plunges deep before backtracking using a stack.
The answer
Representing the graph and avoiding repeats
A graph is often stored as an adjacency list: each node maps to a list of its neighbours. Both traversals keep a visited set so each node is processed once, which also prevents infinite loops on graphs with cycles.
Breadth-first search (BFS)
BFS uses a queue (first in, first out). It visits a node, enqueues its unvisited neighbours, then dequeues the next node - so it fans out level by level from the start:
from collections import deque
def bfs(graph, start):
visited = {start}
queue = deque([start])
order = []
while queue:
node = queue.popleft()
order.append(node)
for neighbour in graph[node]:
if neighbour not in visited:
visited.add(neighbour)
queue.append(neighbour)
return order
Depth-first search (DFS)
DFS uses a stack (last in, first out), or recursion via the call stack. It goes as deep as possible along one path, then backtracks:
def dfs(graph, start, visited=None, order=None):
if visited is None:
visited, order = set(), []
visited.add(start)
order.append(start)
for neighbour in graph[start]:
if neighbour not in visited:
dfs(graph, neighbour, visited, order)
return order
Contrasting the strategies
- BFS explores in order of distance from the start, so in an unweighted graph the first time it reaches a node is by a shortest path (fewest edges). It can use more memory, holding a whole level in the queue.
- DFS dives deep with low memory along one path, ideal for exploring all of a structure, detecting cycles, topological sorting and finding any path. It does not guarantee shortest paths.
Both visit every reachable node, so both run in time for nodes and edges.
Examples in context
Example 1. Shortest route in a maze. Finding the fewest-step path through a grid maze is a BFS: explore all cells one step away, then two steps away, and so on, so the goal is first reached by a shortest path. This is why BFS underlies unweighted shortest-path features in navigation and puzzle solvers.
Example 2. Web crawling and dependency order. A crawler exploring linked pages, or a build tool ordering tasks so dependencies come first (topological sort), uses depth-first search to follow links deeply and backtrack. DFS naturally exposes the structure - cycles, connected components and ordering - that these tasks need.
Try this
Q1. Which data structure drives breadth-first search, and which drives depth-first search? [2 marks]
- Cue. A queue (FIFO) drives BFS; a stack (LIFO), or recursion, drives DFS.
Q2. Why does BFS find the shortest path (in edges) in an unweighted graph? [2 marks]
- Cue. It explores nodes in order of distance from the start, so the first time it reaches a node is by a fewest-edges path.
Q3. Give one task for which depth-first search is better suited than breadth-first search. [1 mark]
- Cue. Cycle detection, topological sorting, or fully exploring a structure such as a maze or folder tree.
Exam-style practice questions
Practice questions written in the style of SEAB exam questions on this dot point, with worked answer explainers. The year tag is the paper they imitate, not the source.
Original6 marksA graph has these adjacency lists: A: [B, C]; B: [A, D, E]; C: [A, F]; D: [B]; E: [B, F]; F: [C, E]. Starting at A and visiting neighbours in the listed order, give the order nodes are visited by (a) breadth-first search and (b) depth-first search.Show worked answer →
(a) Breadth-first search uses a queue and visits all neighbours of a node before going deeper. Starting at A:
Visit A; queue neighbours B, C
Visit B; queue D, E (A already seen)
Visit C; queue F (A already seen)
Visit D; (B seen)
Visit E; (B, F: F not yet visited, already queued check)
Visit F
BFS order: A, B, C, D, E, F.
(b) Depth-first search uses a stack (or recursion) and goes as deep as possible before backtracking. Starting at A, first neighbour B, then B's first new neighbour D (dead end, backtrack), then E, then E's new neighbour F, then F's neighbour C:
DFS order: A, B, D, E, F, C.
Markers reward the BFS level-order using a queue and the DFS deep-first order using a stack, with already-visited nodes skipped via a visited set.
Original5 marks(a) State the data structure that drives breadth-first search and the one that drives depth-first search. (b) Why does breadth-first search find the shortest path (in number of edges) in an unweighted graph? (c) Give one application better suited to depth-first search.Show worked answer →
(a) Breadth-first search is driven by a queue (first in, first out); depth-first search is driven by a stack (last in, first out), or equivalently by recursion using the call stack.
(b) BFS explores the graph in order of distance from the start: all nodes one edge away, then all two edges away, and so on. The first time it reaches a node is therefore by a path with the fewest edges, so for an unweighted graph that path is a shortest path.
(c) Depth-first search suits problems like detecting cycles, topological sorting, exploring a maze fully, or finding any path/connected components, where going deep and backtracking is natural and shortest distance is not required.
Markers reward the queue/stack pairing, the level-by-level argument for BFS shortest paths, and a valid DFS application such as cycle detection or maze exploration.
Related dot points
- Define recursion in terms of base and recursive cases, trace recursive calls, and compare recursion with iteration
A focused answer to the H2 Computing outcome on recursion. Base and recursive cases, tracing the call stack, the divide-and-conquer pattern, and the trade-offs between recursion and iteration.
- Analyse the time and space complexity of an algorithm using Big-O notation, and compare common growth rates
A focused answer to the H2 Computing outcome on algorithmic complexity. Big-O notation, deriving the order of growth from loops and recursion, the common complexity classes, and the trade-off between time and space.
- Describe graphs and their terminology, represent them as adjacency matrices and adjacency lists, and compare the two representations
A focused answer to the H2 Computing outcome on representing graphs. Vertices and edges, directed and weighted graphs, adjacency matrix versus adjacency list, and the space and lookup trade-offs between them.
- Describe stacks (LIFO) and queues (FIFO), implement their core operations, and identify suitable applications of each
A focused answer to the H2 Computing outcome on stacks and queues. The LIFO stack and FIFO queue, their push, pop, enqueue and dequeue operations with overflow and underflow, and typical applications of each.
- Describe a binary search tree, perform insertion, search and in-order traversal, and explain how balance affects complexity
A focused answer to the H2 Computing outcome on binary search trees. The ordering property, inserting and searching nodes, in-order traversal giving sorted output, and why an unbalanced tree degrades to O(n).