0% found this document useful (0 votes)
39 views24 pages

Tree Traversals: ECE 250 Algorithms and Data Structures

The document discusses different ways to traverse tree data structures, including breadth-first and depth-first traversals. Breadth-first traversal visits all nodes at each depth level starting from the root node, while depth-first traversal goes as deep as possible down each branch before backtracking. Depth-first traversal can be implemented recursively by visiting each child node or using a stack. The document provides examples and applications of tree traversals.

Uploaded by

darwinvargas2011
Copyright
© © All Rights Reserved
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
Download as pptx, pdf, or txt
0% found this document useful (0 votes)
39 views24 pages

Tree Traversals: ECE 250 Algorithms and Data Structures

The document discusses different ways to traverse tree data structures, including breadth-first and depth-first traversals. Breadth-first traversal visits all nodes at each depth level starting from the root node, while depth-first traversal goes as deep as possible down each branch before backtracking. Depth-first traversal can be implemented recursively by visiting each child node or using a stack. The document provides examples and applications of tree traversals.

Uploaded by

darwinvargas2011
Copyright
© © All Rights Reserved
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
Download as pptx, pdf, or txt
Download as pptx, pdf, or txt
You are on page 1/ 24

ECE 250 Algorithms and Data Structures

Tree traversals

Douglas Wilhelm Harder, M.Math. LEL


Department of Electrical and Computer Engineering
University of Waterloo
Waterloo, Ontario, Canada

ece.uwaterloo.ca
dwharder@alumni.uwaterloo.ca

© 2006-2013 by Douglas Wilhelm Harder. Some rights reserved.


Tree traversals
2

Outline

This topic will cover tree traversals:


– A means of visiting all the objects in a tree data structure
– We will look at
• Breadth-first traversals
• Depth-first traversals
– Applications
– General guidelines
Tree traversals
3
4.3 Background

All the objects stored in an array or linked list can be accessed


sequentially

When discussing deques, we introduced iterators in C++:


– These allow the user to step through all the objects in a container

Question: how can we iterate through all the objects in a tree in a


predictable and efficient manner
– Requirements: Q(n) run time and o(n) memory
Tree traversals
4
4.3.1 Types of Traversals

We have already seen one traversal:


– The breadth-first traversal visits all nodes at depth k before
proceeding onto depth k + 1
– Easy to implement using a queue

Another approach is to visit always go as deep as possible before


visiting other siblings: depth-first traversals
Tree traversals
5
4.3.1 Breadth-First Traversal

Breadth-first traversals visit all nodes at a given depth


– Can be implemented using a queue
– Run time is Q(n)
– Memory is potentially expensive: maximum nodes at a given depth
– Order: A B H C D G I E F J K
Tree traversals
6
4.3.1 Breadth-First Traversal

The implementation was already discussed:


– Create a queue and push the root node onto the queue
– While the queue is not empty:
• Push all of its children of the front node onto the queue
• Pop the front node
Tree traversals
7
4.3.2 Backtracking

To discuss depth-first traversals, we will define a backtracking


algorithm for stepping through a tree:
– At any node, we proceed to the first child that has not yet been visited
– Or, if we have visited all the children (of which a leaf node is a special
case), we backtrack to the parent and repeat this decision making
process
We end once all the children
of the root are visited
Tree traversals
8
4.3.2 Depth-first Traversal

We define such a path as a depth-first traversal

We note that each node could be visited twice in such a scheme


– The first time the node is approached (before any children)
– The last time it is approached (after all children)
Tree traversals
9
4.3.3 Implementing depth-first traversals

Depth-first traversals can be implemented with recursion:


template <typename Type>
void Simple_tree<Type>::depth_first_traversal() const {
// Perform pre-visit operations on the value
std::cout << "<" << node_value << ">";

// Perform a depth-first traversal on each of the children


for ( auto *child = children.head(); child != children.end();
child = ptr->next() ) {
child->value()->depth_first_traversal();
}

// Perform post-visit operations on the value


std::cout << "</" << node_value << ">";
}
Tree traversals
10

Implementing depth-first traversals

Performed on this tree, the ouput would be


<A><B><C><D></D></C><E><F></F><G></G></E></B><H><I><J></J><K></K><L></L></I><M></M></H></A>
Tree traversals
11
4.3.3 Implementing depth-first traversals

Alternatively, we can use a stack:


– Create a stack and push the root node onto the stack
– While the stack is not empty:
• Pop the top node
• Push all of the children of that node to the top of the stack in reverse order
– Run time is Q(n)
– The objects on the stack are all unvisited siblings from the root to the
current node
• If each node has a maximum of two children, the memory required is Q(h):
the height of the tree

With the recursive implementation, the memory is Q(h): recursion


just hides the memory
Tree traversals
12
4.3.4 Guidelines

Depth-first traversals are used whenever:


– The parent needs information about all its children or descendants, or
– The children require information about all its parent or ancestors

In designing a depth-first traversal, it is necessary to consider:


1. Before the children are traversed, what initializations, operations and
calculations must be performed?
2. In recursively traversing the children:
a) What information must be passed to the children during the recursive call?
b) What information must the children pass back, and how must this
information be collated?
3. Once all children have been traversed, what operations and
calculations depend on information collated during the recursive
traversals?
4. What information must be passed back to the parent?
Tree traversals
13
4.3.4 Applications

Tree application: displaying information about directory structures


and the files contained within
– Finding the height of a tree
– Printing a hierarchical structure
– Determining memory usage
Tree traversals
14
4.3.4.1 Height

The int height() const function is recursive in nature:


1. Before the children are traversed, we assume that the node has no
children and we set the height to zero: hcurrent = 0
2. In recursively traversing the children, each child returns its height h and
we update the height if 1 + h > hcurrent
3. Once all children have been traversed, we return hcurrent

When the root returns a value, that is the height of the tree
Tree traversals
15
4.3.4.2 Printing a Hierarchy

Consider the directory structure presented on the left—how do we


display this in the format on the right?

/
usr/
bin/
local/
var/
adm/
cron/
log/

What do we do at each step?


Tree traversals
16
4.3.4.2 Printing a Hierarchy

For a directory, we initialize a tab level at the root to 0

We then do:
1. Before the children are traversed, we must:
a) Indent an appropriate number of tabs, and
b) Print the name of the directory followed by a '/'
2. In recursively traversing the children:
a) A value of one plus the current tab level must be passed to the children, and
b) No information must be passed back
3. Once all children have been traversed, we are finished
Tree traversals
17
4.3.4.2 Printing a Hierarchy

Assume the function void print_tabs( int n ) prints n tabs

template <typename Type>


void Simple_tree<Type>::print( int depth ) const {
print_tabs( depth );
std::cout << value()->directory_name() << '/' << std::endl;

for ( auto *child = children.head(); child != children.end();


child = ptr->next() ) {
child->value()->print( depth + 1 );
}
}
Tree traversals
18
4.3.4.3 Determining Memory Usage

Suppose we need to determine the memory usage of a directory


and all its subdirectories:
– We must determine and print the memory usage of all subdirectories
before we can determine the memory usage of the current directory
Tree traversals
19
4.3.4.3 Determining Memory Usage

Suppose we are printing the directory usage of this tree:

bin/ 12
local/ 15
usr/ 31
adm/ 6
cron/ 5
log/ 9
var/ 23
/ 61
Tree traversals
20
4.3.4.2 Determining Memory Usage

For a directory, we initialize a tab level at the root to 0

We then do:
1. Before the children are traversed, we must:
a) Initialize the memory usage to that in the current directory.
2. In recursively traversing the children:
a) A value of one plus the current tab level must be passed to the children, and
b) Each child will return the memory used within its directories and this must
be added to the current memory usage.
3. Once all children have been traversed, we must:
a) Print the appropriate number of tabs,
b) Print the name of the directory followed by a "/ ", and
c) Print the memory used by this directory and its descendants
Tree traversals
21
4.3.4.3 Printing a Hierarchy

template <typename Type>


int Simple_tree<Type>::du( int depth ) const {
int usage = value()->memory_usage();

for ( auto *child = children.head(); ptr != children.end();


ptr = ptr->next() ) {
usage += ptr->value()->du( depth + 1 );
}

print_tabs( depth );
std::cout << value()->directory_name() << "/ " << usage << std::endl;

return usage;
}
Tree traversals
22

Summary

This topic covered two types of traversals:


– Breadth-first traversals
– Depth-first traversals
– Applications
– Determination of how to structure a depth-first traversal
Tree traversals
23

References
Tree traversals
24

Usage Notes

• These slides are made publicly available on the web for anyone to
use
• If you choose to use them, or a part thereof, for a course at another
institution, I ask only three things:
– that you inform me that you are using the slides,
– that you acknowledge my work, and
– that you alert me of any mistakes which I made or changes which you
make, and allow me the option of incorporating such changes (with an
acknowledgment) in my set of slides

Sincerely,
Douglas Wilhelm Harder, MMath
dwharder@alumni.uwaterloo.ca

You might also like