Graph Traversals and Applications
Graph Traversals and Applications
• Introduction
• Breadth-First Traversal.
– The Algorithm.
– Example.
– Implementation.
• Depth-First Traversals.
– Algorithms.
– Example.
– Implementation.
– Edge Classification
• Review Questions.
1
Introduction
• A free tree is a connected undirected graph without a cycle.
– Note: This definition of tree is different from the one of a rooted tree
• In a free tree |E| = |V| - 1
• Example of a free tree:
2
Introduction (Cont’d)
• To traverse a graph is to systematically visit and process each node in the
graph exactly once.
• There are two common graph traversal algorithms that are applicable to both directed and
undirected graphs :
• BreadthFirst Traversal (BFS)
• DepthFirst Traversal (DFS)
• PreOrder DepthFirst Traversal
• PostOrder DepthFirst Traversal
• We shall define General traversal algorithms [dfsAllVertices and bfsAllVertices] that will
visit each vertex of a graph G in those algorithms that require each vertex to be visited.
These algorithms will be of the form:
for(i = 0; i < numberOfVertices; i++){
if(vertexi is not visited)
dfsPreOrder(G, vertexi); // or dfsPostOrder(G, vertexi) or bsf(G, vertexi)
}
3
Introduction (Cont’d)
The BFS and DFS traversal of a graph G is not unique. A traversal depends both
on the starting vertex, and on the order of traversing the adjacent vertices of each
node.
4
Breadth-First Traversal Algorithm
• In this method, After visiting a vertex v, we must visit all its adjacent vertices w1, w2,
w3, ..., before going down to the next level to visit vertices adjacent to w1 etc.
BFS-tree:
Order of
Traversal A B D E C G F H I Queue rear
6
Breadth-First Traversal Implementation
public void breadthFirstTraversal(Visitor visitor, Vertex start){
boolean enqueued[] = new boolean[numberOfVertices];
for(int i = 0; i < numberOfVertices; i++) enqueued[i] = false;
8
Depth-First Traversal Algorithm
• A DFS starting at a vertex v first visits v, then some neighbour w of v, then some
neighbour x of w that has not been visited before, etc. When it gets stuck, the DFS
backtracks until it finds the first vertex that still has a neighbour that has not been
visited before. It continues with this neighbour until it has to backtrack again.
Eventually, it will visit all vertices reachable from v
• Note: Adjacent vertices can be pushed in any order; but to obtain a unique traversal, we
will push them in reverse alphabetical order.
9
Example
• Depth-first traversal using an explicit stack.
Order of
A B C F E G D H I Stack
Traversal
}dfsPreorder(v)
;visit v
for(each neighbour w of v)
if(w has not been visited)
;dfsPreorder(w)
{
11
Recursive preorder Depth-First Traversal Implementation (cont’d)
Iterator p = v.getSuccessors();
while(p.hasNext()) {
Vertex to = (Vertex) p.next();
if(! visited[getIndex(to)])
preorderDepthFirstTraversal(visitor, to,
visited);
}
}
12
Recursive preorder Depth-First Traversal Tracing
13
Recursive postorder Depth-First Traversal Implementation
}dfsPostorder(v)
;mark v
for(each neighbour w of v)
if(w is not marked)
;dfsPostorder(w)
;visit v
{
// mark v
visited[getIndex(v)] = true;
Iterator p = v.getSuccessors();
while(p.hasNext()){
Vertex to = (Vertex) p.next();
if(! visited[getIndex(to)])
postorderDepthFirstTraversal(visitor, to,
visited);
}
// visit v
visitor.visit(v);
}
15
Recursive postorder Depth-First Traversal Tracing
16
Analysis of DFS
For a Graph G=(V, E) and n = |V| and m=|E|
• When Adjacency List is used
Complexity is O(m + n)
• When Adjacency Matrix is used
Scanning each row for checking the connectivity of a Vertex
is in order O(n).
So, Complexity is O(n2)
DFS uses space O(|V|) in the worst case to store the stack of vertices
on the current search path as well as the set of already-visited vertices.
17
Connected Components (CCs)
dfsAllVertices(G)
}
/* c = 0; /* component number
for (i = 0; i < numberOfVertices; i++)
} if (vertexi is not visited)
;++c
;output("Component ” + c)
;dfsPreorder(G, vertexi)
{
{
18
DFS Numbering
• Let G be a directed or undirected graph.
• Let Ti be a DFS (Depth First Search) tree.
• Let d[v] be the discovery time and f[v] be the finishing time of a vertex v of G. The first timestamp d[v]
records when v is first discovered, and the second timestamp f[v] records when the search finishes
examining v's adjacent vertices.
The following algorithm builds DFS tree(s) of a graph G and calculates the discovery and finishing times of
each vertex: dfsAllVertices(G){
time = 0; // Let time be a global variable
mark each vertex of G as NOT VISITED;
for(i = 0; i < numberOfVertices; i++){
if(vertexi is not visited){
Add vertexi to tree Ti;
dfsPreOrder(vertexi, G, Ti);
}
}
}
dfsPreOrder(v, G, T){
visit(v);
mark v as VISITED;
d[v] = ++time;
for(each neighbour w of v){
if(w is NOT VISITED){
add edge (v, w) to tree T;
dfsPreOrder(w, G, T);
}
f[v] = ++time;
}
} 19
Strongly Connected Components (SCCs)
• A strongly connected component in a directed graph G = (V, E) is a maximal set of
vertices such that for every pair of vertices u and v in the component, vertices u
and v are reachable from each other.
• If G = (V, E) is a directed graph, its transpose, GT = (V, ET) is the same as G with
all arrows reversed.
KOSARAJU’S ALGORITHM FOR FINDING SCCs of a graph G:
20
Strongly Connected Components (Cont’d)
We can translate Kosaraju’s algorithm to the following algorithm:
• Perform a DFS on G, each time a vertex is assigned finish time, push it in a
stack S
• Create GT, the transpose of G
• Initialize each vertex in GT as not visited
• while(stack S is not empty){
Pop a vertex v from S
If(v is not visited){
Mark v as visited
dfsPreOrder(v, GT) // mark each unvisited reachable vertex as visited
Output all visited vertices in the above dfs as a strongly connected component
}
}
21
Strongly Connected Components (Cont’d)
Example: Find the SCCs of the graph below. Use A as the start vertex and DFS
traversal:
1. Perform dfsAllVertices(G) and
compute the discovery and
finish times of each vertex,
push each finished vertex in a
stack:
2. Create GT
Note:
• The way we classify the edges is not unique; it depends on what node we start from
and in what order the algorithm happens to select successors to visit.
24
Edge Classification using DFS (Cont’d)
Example2: Classify the edges in the following directed graph. Use vertex A as the starting
vertex. If at any point in the DFS search it is possible to visit more than one vertex, visit the
vertices in increasing alphabetical order.
25
Edge Classification using DFS (Cont’d)
• DFS can be modified to classify edges as it encounters them
• During the traversal the discovery and finish times are computed and vertices are colored
as:
• white: if the vertex is not visited
• gray: when the vertex is first encountered during the traversal
• black: if the vertex and all its adjacent vertices have been visited
• An edge e = (v, w) is classified based on the color of vertex w when e is first explored:
Forward edge – if w is black and d[v] < d[w] (w was discovered after v)
26
Edge Classification using DFS (Cont’d)
The DFS Edge classification algorithm for directed graphs:
dfsAllVertices(G){
color all vertices white;
time = 0;
for( each v ∈ V)
if (color[v] == “white”) DFS(v);
}
DFS(v){
color[v] = “gray”;
d[v] = ++time;
[previsit(v)]
for (each w adjacent to v){
if(w is white) edge(v, w).Type = “treeEdge”;
else if(w is gray) edge(v, w).Type = “backEdge”;
else if(d[v] < d[w]) edge(v, w).Type = “forwardEdge”; // w is black
else edge(v, w).Type = “crossEdge”; // w is black
if (color[w] == “white”){
[ Add edge (v, w) to DFS tree]
DFS(w)
}
}
f[v] = ++time;
[postvisit(v)]
color[v] = “black”;
}
27
Edge Classification using DFS (Cont’d)
Exercise: Run the DFS edge classification algorithm on the following graph, starting at
vertex 1, to obtain the classification given below:
28
Edge Classification using BFS
BFS has the useful feature that its tree edges from a given vertex s define paths from s that
have a minimum number of edges.
29
Review Questions
30