CS 312 Recitation 15
Tree Traversal

CS312: October 20, 2004

Harlan Crystal <hpc4@cornell.edu>

Introduction

Suppose we want to traverse at every node in this tree. One motivating reason to do this would be to look through each of the nodes searching for a value, or walking through the nodes trying to find the minimum value. There are multiple ways to order this traversal through the set of nodes. The ones we will discuss depth first search and breath first search.

Depth First Search

Depth first search would traverse the nodes in the following order: A, B, D, E, C, F, G.

Depth first search visits the children the current node before the neighbors of the current node. As the name implies, this means that the traversal goes as deep as it can before stepping back and visiting nodes on the current level. We venture along a single path away from the starting node until there are no more undiscovered nodes in front of us, and only then step back and continue trying to go as deep as we can in our search for undiscovered nodes.

Breath First Search

Breath first search would traverse the nodes in the following order: A, B, C, D, E, F, G.

Breath first search visits the neighbors of the current node before the children of the current node. Before searching any nodes which are k+1 hops away from the root of the tree, we search all nodes which are at depth k. As the name breath first search implies, we are searching as widey as we can on each level before searching deeper to the next level.

Performing the Search

While doing the search, nodes can be classified as "visited", "undiscovered", or "discovered". A node has been visited if we have already traversed it. A node is "undiscovered" if we have not yet seen it at all during the traveral. A node is "discovered" if we have seen the node and know that we still need to traverse it, but have no yet done so. Consider the following psuedo-code for doing the traversal:

let s = A collection of nodes, initialized to empty.

Add the root node of the tree to the collection s.

While s is not empty:
   Remove the first element in the collection s and call it n.
   Visit n.
   Add all of n's children to the collection s.

In this code, s is the collection of nodes which have been discovered but not yet visited.

Consider what would happen if we used a stack data structure for s. Since stacks are LIFO, when nodes are added to the collection s, they will be first ones to be removed. If a node n has jsut been visited, its children will be added to the stack and will be processed before all the nodes already in the stack. Any neighbors of n are already in the stack, so they will be visited after all the children of n This is exactly how we described depth first search. Using a stack for s in this traversal algorithm means that we will perform a depth first search.

Consider what would happen if we used a queue data structure for s. Since queues are FIFO, when a nodes are added to the collection s they are the last ones to be removed. If a node n has just been visited, its children will be added to the queue and be processed after all the nodes which are already in the queue. Any neighbors of n are already in the queue, so they will be visited before the children of n. This is exactly how we described breath first search. Using a queue for s in this traversal algorithm means that we will perform a breath first search.