Graph Traversal
Graph Traversal with DFS/BFS
One of the most fundamental graph problems is to traverse every
edge and vertex in a graph.
Tyler Moore
CSE 3353, SMU, Dallas, TX
For correctness, we must do the traversal in a systematic way so that
we dont miss anything.
Lecture 6
For efficiency, we must make sure we visit each edge at most twice.
Since a maze is just a graph, such an algorithm must be powerful
enough to enable us to get out of an arbitrary maze.
Some slides created by or adapted from Dr. Kevin Wayne. For more information see
http://www.cs.princeton.edu/~wayne/kleinberg-tardos
2 / 20
Marking Vertices
To Do List
The key idea is that we must mark each vertex when we first visit it,
and keep track of what have not yet completely explored.
Each vertex will always be in one of the following three states:
1
2
3
undiscovered the vertex in its initial, virgin state.
discovered the vertex after we have encountered it, but before we have
checked out all its incident edges.
processed the vertex after we have visited all its incident edges.
A vertex cannot be processed before we discover it, so over the course
of the traversal the state of each vertex progresses from undiscovered
to discovered to processed.
3 / 20
We must also maintain a structure containing all the vertices we have
discovered but not yet completely explored.
Initially, only a single start vertex is considered to be discovered.
To completely explore a vertex, we look at each edge going out of it.
For each edge which goes to an undiscovered vertex, we mark it
discovered and add it to the list of work to do.
Note that regardless of what order we fetch the next vertex to
explore, each edge is considered exactly twice, when each of its
endpoints are explored.
4 / 20
In what order should we process vertices?
Depth-First Traversal
Undirected Graph
Depth-First Search Tree
a
1
7
Last-in-first-out: if we use a stack to process discovered vertices, we
use depth-first search
b
c
a
c
f
d
4
Discovered:
Processed:
e
abcdef
edcbf a
e
5 / 20
Recursive Depth-First Traversal Code
def r e c d f s (G , s , S=None ) :
i f S i s None : S = s e t ( )#
S . add ( s )
#
for u in G[ s ] :
#
i f u i n S : c o n t i n u e#
#
r e c d f s (G , u , S )
3
d
f
6
2
b
5
First-in-first-out: if we use a queue to process discovered vertices, we
use breadth-first search
2
1
6 / 20
Iterative Depth-First Traversal Code
I n i t i a l i z e the h i s t o r y
We ’ ve v i s i t e d s
Explore neighbors
Already v i s i t e d : Skip
New : E x p l o r e r e c u r s i v e l y
>>> r e c d f s t e s t e d (G , 0 )
[0 , 1 , 2 , 3 , 4 , 5 , 6 , 7]
def i t e r d f s (G , s ) :
S, Q = set () , [ ]
#
Q. append ( s )
#
w h i l e Q:
#
u = Q. pop ( )
#
i f u i n S : c o nt i n u e#
S . add ( u )
#
Q. e x t e n d (G [ u ] )
#
yield u
#
V i s i t e d −s e t and queue
We p l a n on v i s i t i n g s
Planned nodes l e f t ?
Get one
Already v i s i t e d ? Skip i t
We ’ ve v i s i t e d i t now
Schedule a l l neighbors
Report u as v i s i t e d
>>> l i s t ( i t e r d f s (G , 0 ) )
[0 , 5 , 7 , 6 , 2 , 3 , 4 , 1]
7 / 20
8 / 20
Breadth-First Traversal
Breadth-First Search Tree
b
a
When you execute a function, it normally returns values
Nice explanation on Stack Overflow: http://stackoverflow.com/
questions/231767/the-python-yield-keyword-explained
a
b
d
f
Discovered:
Processed:
e
5
4
Especially helpful when the object you’re iterating over is very large,
and you don’t want to keep the entire object in memory
1
c
Useful when you don’t need to keep the list of values you loop over
c
e
3
Generators only execute code when iterated
2
Undirected Graph
f
6
What does the yield command do?
7
d
abef cd
abef cd
9 / 20
Breadth-First Traversal Code
10 / 20
Correctness of Graph Traversal
from c o l l e c t i o n s import deque
def i t e r b f s (G , s , S = None ) :
S , Q = s e t ( ) , deque ( ) # V i s i t e d −s e t and queue
Q. append ( s )
# We p l a n on v i s i t i n g s
w h i l e Q:
# Planned nodes l e f t ?
u = Q. p o p l e f t ( )
# Get one
i f u i n S : c o n t i n u e# A l r e a d y v i s i t e d ? S k i p i t
S . add ( u )
# We ’ ve v i s i t e d i t now
Q. e x t e n d (G [ u ] )
# Schedule a l l neighbors
yield u
# Report u as v i s i t e d
11 / 20
Every edge and vertex in the connected component is eventually
visited. Why?
Suppose it’s not correct, ie. there exists an unvisited vertex A whose
neighbor B was visited.
When B was visited, each of its neighbors was added to the list to be
processed. Since A is a neighbor of B, it must be visited before the
algorithm completes.
12 / 20
Preorder vs. postorder processing
Preorder and postorder processing with BFS
Many useful algorithms are built on top of BFS or DFS traversal
Frequently, extra code is added either immediately before a node is
processed (preorder processing) or after a node is processed
(postorder processing)
d e f b f s p p (G , s , S = None ) :
S , Q = s e t ( ) , de q u e ( ) # V i s i t e d −s e t and qu eu e
Q. append ( s )
# We p l a n on v i s i t i n g s
w h i l e Q:
# Planned nodes l e f t ?
u = Q. p o p l e f t ( )
# Get one
i f u i n S : c o n t i n u e# A l r e a d y v i s i t e d ? S k i p i t
’+u
# p r e o r d e r p r o c e s s i n g −− aka p r o c e s s v e r t e x e a r l y (ADM)
pr i nt ’ pre
S . add ( u )
# We ’ v e v i s i t e d i t now
Q. e x t e n d (G [ u ] )
# Schedule a l l neighbors
yield u
# Report u as v i s i t e d
# p o s t o r d e r p r o c e s s i n g −− aka p r o c e s s v e r t e x l a t e
p r i n t ’ −−−−−− p o s t ’+u
>>> l i s t ( b f s p p (N, ’ a ’ ) )
pre a
−−−−−− p o s t a
pre b
−−−−−− p o s t b
pre e
−−−−−− p o s t e
pre
f
−−−−−− p o s t f
pre c
−−−−−− p o s t c
pre d
−−−−−− p o s t d
[ ’a ’ , ’b ’ , ’e ’ , ’ f ’ , ’c ’ , ’d ’ ]
13 / 20
DFS Trees: all descendants of a node u are processed after
u is discovered but before u is processed
Undirected Graph
Depth-First Search Tree
a
b
b
15 / 20
d
abcdef
edcbf a
4
Discovered:
Processed:
e
3
f
6
c
5
a
d
f
2
c
>>> l i s t ( r e c d f s p p (N, ’ a ’ ) )
pre : a
pre : b
pre : c
pre : d
pre : e
−−−−−− p o s t : e
−−−−−− p o s t : d
−−−−−− p o s t : c
−−−−−− p o s t : b
pre : f
−−−−−− p o s t : f
−−−−−− p o s t : a
[ ’a ’ , ’c ’ , ’b ’ , ’e ’ , ’d ’ , ’ f ’ ]
10
d e f r e c d f s p p (G , s , S=None ) :
i f S i s None : S = s e t ( )# I n i t i a l i z e t h e h i s t o r y
S . add ( s )
# We ’ v e v i s i t e d s
# p r i n t node −− p r e o r d e r p r o c e s s i n g
p r i n t ’ p r e : ’+s
for u in G[ s ] :
# Explore neighbors
i f u i n S : c o n t i n u e# A l r e a d y v i s i t e d : S k i p
# New : E x p l o r e r e c u r s i v e l y
r e c d f s p p (G , u , S )
p r i n t ’−−−−−− p o s t : ’+s
# p r i n t node −− p o s t o r d e r p r o c e s s i n g
return S
1
Preorder and postorder processing with DFS
14 / 20
e
16 / 20
How can we tell if one node is a descendant of another?
Code for depth-first timestamps
Answer: with depth-first timestamps!
After we create a graph in a depth-first traversal, it would be nice to
be able to verify if node A is encountered before node B, etc.
We add one timestamp for when a node is discovered (during preorder
processing) and another timestamp for when a node is processed
(during postorder processing)
def d f s (G , s , d , f , S=None , t =0):
i f S i s None : S = s e t ( )# I n i t i a l i z e t h e h i s t o r y
d [ s ] = t ; t += 1
# Set d i s c o v e r time
S . add ( s )
# We ’ ve v i s i t e d s
for u in G[ s ] :
# Explore neighbors
i f u i n S : c o nt i n u e# A l r e a d y v i s i t e d . S k i p
t = d f s (G , u , d , f , S , t )
# Recurse ; update
f [ s ] = t ; t += 1
# Set f i n i s h time
return t
# Return timestamp
>>> f ={}
>>> d={}
>>> d f s (N, ’ a ’ , d , f )
12
>>> d
{ ’ a ’ : 0 , ’ c ’ : 2 , ’ b ’ : 1 , ’ e ’ : 4 , ’ d ’ : 3 , ’ f ’ : 9}
>>> f
{ ’ a ’ : 1 1 , ’ c ’ : 7 , ’ b ’ : 8 , ’ e ’ : 5 , ’ d ’ : 6 , ’ f ’ : 10}
17 / 20
Edge cases for DFS/BFS traversal
Tree edges
a
e
d
d
e
d
Cross edges
a
c
e
c
b
Back edge
a
b
Edge classification
Forward edge
a
c
b
18 / 20
Edge (u, v ) is a tree edge if v was first discovered by exploring edge
(u, v ).
2
Edge (u, v ) is a back edge if vertex u is connected to an ancestor v .
3
Edge (u, v ) is a forward edge if vertex u is connected to a
descendant v .
4
All other edges are cross edges
c
b
d
1
e
19 / 20
20 / 20
© Copyright 2026 Paperzz