COMP2521
Data Structures & Algorithms
Week 5.3
Graph Traversal
Author: Hayden Smith 2021
In this lecture
Why?
- Graphs aren't very useful if all we're doing is storing things in them. We need to effectively search and traverse them to gather information
What?
- Traverse and searching a graph
- Breadth-first-search
- Depth-first-search
Why do we use graphs?
Allow us to ask these kinds of questions:
- Can we remove an edge and keep the graph connected?
- Is a vertex reachable starting from somewhere else?
- What is the quickest way to get from one node to another?
- Is there a tree that links all vertices?
Why do we use graphs?
There are 3 topics we will focus on relating to traversal. All rely on very similar algorithms and processes, they're just used to different extents.
Traverse for Item Searching
Using an algorithm to move between nodes to look for a value
Traverse for Path Finding
Using an algorithm to look for a value, but keep track of how to get there
Traverse Fully
Like path finding, except we're just exploring the entire graph, not looking for specific value
Graph Traversal (/Search)
Graph Traversal is the systematic exploration of a graph via the edges. The focus is often between exploring paths between a starting vertex and a finish vertex.
- Solutions can be iterative or recursive
- Sometimes need to store the path we explore as we explore it, and sometimes store a list of nodes we've visited
Graph Traversal
There are two primary methods we'll be using to traverse a graph:
- Depth-first search (go deep)
- Iterative & recursive solutions
- Breadth-first search (go wide)
- Iterative solutions

Graph Traversal
Both approaches ignore some edges by remembering previously visited vertices (this also prevents cycles)

Breadth First Search
Traversing with BFS is about start at a node, and expanding out equally from there. You visit all the neighbours of the current vertex, then you visit all the neighbours of those neighbours. Etc.
BFS - Example Path Find

BFS - Algorithm
A very tricky algorithm to describe recursively. Typically we do it iteratively
findPathBFS(G,src,dest):
visited[] // store previously visited node
for all vertices v∈G:
visited[v]=-1
found = false
visited[src] = src
enqueue src into queue Q
while not found ∧ Q is not empty:
dequeue v from Q
if v = dest:
found = true
else:
for each (v,w) ∈ edges(G) with visited[w] = -1:
visited[w] = v
enqueue w into Q
end while
if found:
display path in dest..src order
BFS - Cost Analysis
For an adjacency list representation:
Each vertex visited at most once. Cost => O(V)
Visit all edges incident on visited vertices. Cost => O(E)
BFS: O(V + E) (adjacency list)
Depth First Search
Traversing with DFS is about going as deep as possible until you reach a dead end, and then unwinding back through nodes until there is another branch to take.
DFS - Algorithm
An iterative DFS is identical to an iterative BFS, except we use a stack instead of a queue.
findPathDFS(G,src,dest):
visited[] // store previously visited node
for all vertices v ∈ G:
visited[v] = -1
found = false
visited[src] = src
push src into stack S
while not found ∧ Q is not empty:
pop stack from S
if v = dest:
found = true
else:
for each (v,w) ∈ edges(G) with visited[w] = -1:
visited[w] = v
push w into stack S
end while
if found:
display path in dest..src order
DFS - Recursive
Recursive solutions are a bit more elegant.
Full Traversal
Path Checking
visited = {}
depthFirst(G,v):
visited = visited ∪ {v}
for all (v,w) ∈ edges(G):
if w ∉ visited:
depthFirst(G,w)
visited = {}
hasPath(G,src,dest):
return dfsPathCheck(G,src,dest)
dfsPathCheck(G,v,dest):
visited = visited ∪ {v}
for all (v,w) ∈ edges(G):
if w = dest: // found edge to dest
return true
else if w ∉ visited:
if dfsPathCheck(G,w,dest):
return true // found path via w to dest
return false // no path from v to dest
Path Finding
visited[] // store previously visited node
findPath(G,src,dest):
for all vertices v ∈ G:
visited[v] = -1
visited[src] = src // starting node of the path
if dfsPathCheck(G,src,dest):
// show path in dest..src order
v = dest
while v ≠ src:
print v"-"
v = visited[v]
print src
dfsPathCheck(G,v,dest):
for all (v,w) ∈ edges(G):
if visited[w] = -1:
visited[w] = v
if w = dest: // found edge from v to dest
return true
else if dfsPathCheck(G,w,dest):
return true // found path via w to dest
return false // no path from v to dest
DFS - Recursive Path Find

DFS - Cost Analysis
For an adjacency list representation:
Each vertex visited at most once. Cost => O(V)
Visit all edges incident on visited vertices. Cost => O(E)
BFS: O(V + E) (adjacency list)
DFS - Other
DFS does not guarantee optimal solution
Example below clearly does not find shortest path

Full Traversal
A full traversal of a tree is essentially using BFS or DFS to find a spanning tree


Feedback

COMP2521 21T2 - 5.3 - Graph Traversal
By haydensmith
COMP2521 21T2 - 5.3 - Graph Traversal
- 2,176