Basic Traversal and Search Techniques
Basic Traversal and Search Techniques
Traversal vs Search
Definition 1 Traversal of a binary tree involves examining every node in the tree.
Definition 2 Search involves visiting nodes in a graph in a systematic manner, and may or may not result into a visit to all
nodes.
• Different nodes of a graph may be visited, possibly more than once, during traversal or search
• If search results into a visit to all the vertices, it is called traversal
– Possible problem: Find all nodes in a binary tree with data value less than some specified value
∗ Solved by systematically examining all the vertices
∗ Does searching for a specified item in a binary search tree result into a traversal?
struct tree_node_type
{
item_type data; // To hold information at each node
tree_node_type left_child;
tree_node_type right_child;
};
Algorithm inorder ( t )
// Input: t is a binary tree
// Each node of t is of type tree_node_type
{
if ( t != NULL )
{
inorder ( t.left_child );
visit ( t ); // Perform a function on data in node being traversed
inorder ( t.right_child );
}
}
Algorithm preorder ( t )
// Input: t is a binary tree
// Each node of t is of type tree_node_type
{
if ( t != NULL )
{
visit ( t ); // Perform a function on data in node being traversed
Basic Traversal and Search Techniques 2
preorder ( t.left_child );
preorder ( t.right_child );
}
}
Algorithm postorder ( t )
// Input: t is a binary tree
// Each node of t is of type tree_node_type
{
if ( t != NULL )
{
postorder ( t.left_child );
postorder ( t.right_child );
visit ( t ); // Perform a function on data in node being traversed
}
}
Theorem 1 Let Tn and Sn represent the time and space needed by any one of the traversal algorithms when the input
tree t has n ≥ 0 nodes. If the time and space needed to visit a single node is Θ(1), then Tn = Θ(n) and Sn = O(n).
Proof:
– Each node in the tree is visited three times, requiring constant amount of work
1. From parent (or start node, if root)
2. Return from left subtree
3. Return from right subtree
– This gives the total time required for traversal to be Θ(n)
– Additional space is required for recursion stack
∗ If t has depth d, this space is given by Θ(d)
∗ For an n-node binary tree, d ≤ n
∗ Hence, Sn = O(n)
• Level-order traversal
– Determine whether a vertex v is reachable from a vertex u in a graph G = (V, E); or whether there exists a path
from u to v
– A more general form: Given a vertex u ∈ V , find all vertices vi ∈ V such that there is a path from u to vi
∗ Solved by starting at vertex u and systematically searching the graph G for vertices reachable from u
return ( NULL );
}
– Example: Undirected graph G = (V, E)
∗ V = {1, 2, 3, 4, 5, 6, 7, 8}
∗ E = {1 − 2, 1 − 3, 2 − 4, 2 − 5, 3 − 6, 3 − 7, 4 − 8, 5 − 8, 6 − 8, 7 − 8}
– Example: Directed graph G = (V, E)
∗ V = {1, 2, 3, 4}
∗ E = {1 − 2, 2 − 3, 4 − 1, 4 − 3}
∗ Starting at vertex 1, vertex 4 is not reachable
– Notice the similarity between breadth-first search and level-order traversal
return ( NULL )
}
– dfs visits all vertices reachable from vertex u
– If T (|V |, |E|) and S(|V |, |E|) represent the maximum time and maximum additional space taken by dfs, then
S(|V |, |E|) = Θ(|V |) and T (|V |, |E|) = Θ(|V | + |E|) if adjacency lists are used and T (|V |, |E|) = Θ(|V |2 ) if
adjacency matrices are used
• BFS vs DFS
– BFS fully explores a node before the exploration of other nodes
∗ The next node to explore is the first unexplored remaining node
– DFS suspends exploration of the node as soon as another unexplored node is encountered
∗ The exploration of the new node is started immediately
• G is a connected undirected graph implies that all vertices will be visited in the first call to bfs
– If G is not connected, you have to make a call to bfs for each of the connected components
– The above property can be used to check if a given graph G is connected
– All newly visited vertices on a call to bfs from bft represent the vertices in a connected component of G
∗ Connected components of a graph can be found using bft
∗ Modify bfs so that all newly visited vertices are put onto a list
∗ Subgraph formed by the vertices on this list make up a connected component
∗ If adjacency lists are used, a breadth-first traversal will obtain the connected components in Θ(n + e) time
• Use bfs to compute a spanning tree in a graph
– A graph G has a spanning tree iff G is connected
∗ BFS easily determines the existence of a spanning tree
– The set of edges used in the traversal of the tree are known as forward edges
∗ If t is the set of forward edges and G is connected, then t is the spanning tree of G
– The computed spanning tree is not a minimum spanning tree
– Breadth-first spanning tree and depth-first spanning tree
• The check for connected components as well as the computation of spanning tree can be performed using dfs as well
– The spanning trees given by bfs and dfs are not identical
Definition 3 A vertex v in a connected graph G is an articulation point iff the deletion of v from G, along with the
deletion of all edges incident to v, disconnects the graph into two or more nonempty components.
– Graph G = (V, E)
Basic Traversal and Search Techniques 6
m
10 9m8m
@ A
@ A
4m 3m 7mA
@
1m 2m 5m 6m
• Biconnected graph
Lemma 1 Two biconnected components can have at most one vertex in common and this vertex is an articulation
point.
∗ No edge can be in two different biconnected components; this will require two common vertices
∗ Graph G can be transformed into a biconnected graph by using the edge addition scheme in the following
algorithm
algorithm mk_biconnected
// Input: Graph G = ( V, E )
{
for each articulation point a
{
Basic Traversal and Search Techniques 7
Lemma 2 If (u, v) is any edge in G, then relative to the depth first spanning tree t, either u is an ancestor of v or v is an
ancestor of u. So, there are no cross edges relative to a depth first spanning tree.
Lemma 3 The root node of a depth first spanning tree is an articulation point iff it has at least two children. Furthermore,
if u is any other vertex, then it is not an articulation point iff from every child w of u it is possible to reach an ancestor of
u using only a path made up of descendents of w and a back edge.
– If it cannot be done for some child w of u, the deletion of vertex u leaves behind at least two nonempty components
– one containing the root and the other containing vertex w
– Identifying articulation points using the above observation
∗ For each vertex u, define L[u] as
df n[u],
L[u] = min L[w] | w is a child of u,
min
min{df n[w] | (u, w) is a back edge}
∗ L[u] is the lowest df n reachable from u using a path of descendants followed by at most one back edge
Basic Traversal and Search Techniques 8
∗ If u is not the oot, then u is an articulation point iff u has a child w such that L[w] ≥ df n[u]
– Example:
∗ Spanning tree
m
10 9m 8m
@ A
@
A
4m 3m 7mA
@
1m 2m 5m 6m
if ( dfn[w] = 0 ) // w is unvisited
{
if ( L[w] >= dfn[u] )
{
write ( "New bicomponent" );
repeat
{
pop an edge (x,y) from the top of stack s;
write ( x, y );
} until ( ( ( x, y ) = ( u, w ) ) ||
( ( x, y ) = ( w, u ) ) );
}
bi_comp ( w, u );
L[u] = min ( L[u], L[w] );
}
else
if ( w != v )
L[u] = min ( L[u], dfn[w] );
}
}
Theorem 4 Algorithm bi comp correctly generates the biconnected components of the connected graph G
when G has at least two vertices.
Proof by induction on the number of biconnected components in G
Base case
· For all biconnected graphs G, root u of the depth-first spanning tree has only one child w
· w is the only vertex for which L[w] ≥ df n[u] in bi_comp
· By the time w has been explored, all edges in G have been output as one biconnected component
Induction hypothesis
· Assume that bi_comp works correctly for all connected graphs G with at most m biconnected compo-
nents
Induction step
· Let G be a graph with m + 1 connected components
· Consider the first time that L[w] ≥ df n[u] in the line whose success writes New bicomponent
· At this time no edges have been output and so all edges in G incident to the descendents of w are on the
stack and above the edge (u, w)
· Since none of the descendents of u is an articulation point and u is, the set of edges above (u, w) on the
stack form a biconnected component together with (u, w)
· Once these edges have been deleted from the stack and output, the algorithm behaves essentially the
same as it would on the graph G0 obtained by deleting from G the biconnected component just output
Basic Traversal and Search Techniques 10
· The behavior of algorithm on G differs from that on G0 only in that during the exploration of vertex u,
some edge (u, r) such that (u, r) is in the component just considered may be considered
· However, for all such edges, df n[r] 6= 0 and df n[r] > df n[u] ≥ L[u]
· Hence, the edges only result in a vacuous iteration of the for loopand do no materially affect the
algorithm
· It can be easily established that G0 has at least two vertices
· Since G0 has exactly m biconnected components, it follows from the induction hypothesis that remaining
components are correctly generated QED
– Articulate will work with any spanning tree relative to which the given graph has no cross edges
∗ Graphs can have cross edges relative to breadth first spanning trees; hence Articulate cannot be adapted
to BFS