Lecture05 Tree
Lecture05 Tree
Lecture 5 Tree
1
Outline
• Tree
• Binary tree
• Tree Traversal
2
Tree
3
Tree
• We have learned four data structures:
• Array, linked list, stack and queue
• These four data structures are linear data structure
(the data are arranged as a sequence)
• However, some data naturally comes with a
hierarchy. It is inconvenient to store and
process these data using linear data structure
• Example: files and folders in a computer system,
• Example: decision tree in machine learning
(classification trees, regression trees)
4
Tree
5
Tree
• A tree data structure
stores information in
nodes root
• Similar to linked list
• There is a first node (the first
node is called root in tree)
• Each node, other than the
root, has exactly one node
pointing to it
• Different from linked list
• Each node in a tree may have
more than one references to
successors
• Each node in a linked list has
only one reference to a
successor
6
Tree
• We will learn the following concepts of tree:
• Root, internal, leaf nodes
• Parents, children, and siblings
• Paths, path length, height, and depth
• Ancestors and descendants
• Ordered and unordered trees
• Subtrees
7
Terminology: Parent
8
Terminology: Child
9
Terminology: Siblings
10
Terminology: degree
11
Terminology: leaf node, internal node
12
Leaf nodes:
13
Terminology: path
14
Example: Paths of length 10 (11 nodes) and 4 (5 nodes)
15
Terminology: depth
16
Terminology: level
17
Nodes of depth up to 17
Level 0
Level 4
Level 9
Level 14
Level 17
18
Terminology: Height
19
The height of this tree is 17
17
20
Terminology: ancestor, descendent
21
• The descendants of node B are B, C, D, E, F, and G:
22
All descendants (including itself) of the indicated node
23
All ancestors (including itself) of the indicated node
24
Terminology: subtree
25
Binary Tree
26
Binary Tree
27
Some binary tree examples with five nodes
28
Tree Traversal
29
Tree Traversal
• Tree traversal is a process to visit all the nodes of
a tree (and may print their values)
• A typical reason to traverse a tree is to display the data
stored at each node of the tree
• In this course, we learn four standard tree
traversal orderings:
• Preorder
• Inorder
• Postorder
• Level-order
30
Tree Traversal
• Depth-first traversal: go deeper in the tree before
exploring siblings
• Preorder
• Inorder
• Postorder
• Breath-first traversal: explore the breadth, i.e., full
width of the tree at a given level, before going
deeper
• Level-order
• We will learn the binary tree traversal in this course
• The traversals can be generalized to other trees
31
Traversals
A
B C
D E F G
H I
We’ll trace the different traversals using this tree; recursive calls,
returns, and “visits” will be numbered in the order they occur
32
Tree Traversal:
Depth-First Traversal
33
Preorder Traversal
• Start at the root
• Visit each node, followed by its left subtree, then right
subtree
34
Preorder Traversal
1: visit A
2 24
23 45
3: visit B 25: visit C
4 16 26 38
15 22 37 44 39:
5: visit D 17: visit E 27: visit F visit G
. . . .
6 18
. 7 14
8
19
20
9: visit H
21 28
34
35
29: visit I
36
40
41
42
43
10
. .11 12
13
30
. .31 32
33
B C
D E F G
H I
36
Inorder Traversal
• Start at the root
• Visit the left subtree of each node, then the node,
then the right subtree of that node
37
Inorder Traversal
23: visit A
1 24
22 45
14: visit B 37: visit C
2 15 25 38
13 21 36 44 41:
5: visit D 18: visit E 33: visit F
visit G
. . . .
3 16
. 4 12
6
17
19
9: visit H
20 26
32
34
29: visit I
35
39
40
42
43
7
. . 8 10
11
27
. .28 30
31
B C
D E F G
H I
39
Postorder Traversal
• Start at the root
• Visit the children of each node, then the node
40
Postorder Traversal
45: visit A
1 23
22 44
21: visit B 43: visit C
2 14 24 36
13 20 35 42 41:
12: visit D 19: visit E 34: visit F
visit G
. . . .
3 15
. 4 11
5
16
17
10: visit H
18 25
31
32
30: visit I
33
37
38
39
40
6
. .7 8
9
26
. . 27 28
29
B C
D E F G
H I
42
Implementation of Depth-First Traversal
• Stack is needed for implementing depth-first traversal
• For example, for the tree shown below, for preorder traversal,
1) when we visit node A, before visiting its left child B, we need to
store its right child C so that we can visit C after visiting the
subtree rooted at B.
2) when visiting node B, before visiting its left child D, we need to
store its right child E
3) when visiting node D, before visiting its left child, we need to
store its right child H
4) we notice that we now stored nodes C, E, H, and we will visit
node H first, after visiting the subtree rooted at H, visit node E,
after visiting the subtree rooted at E, visit node C.
5) The node being stored most recently will be visited first (Last-
in-first-out), so stack is used
43
Implementation of Depth-First Traversal
• The simplest way to implement the depth-first
traversal is to use recursive functions
• Note that function calls are implemented using stack
(Before calling a function, the next code address is
stored on the stack. After the function call, pop the
code address from the stack and continue execution)
• An alternative way to implement the depth-first
traversal is to use the stack explicitly in the
iterative approach
• We will use preorder traversal as example to
illustrate the recursive and iterative approaches
in the following slides.
44
Example 1:
Recursive Implementation of Preorder Traversal
45
Recursive Preorder Traversal
Visited nodes:
47
• Visit A
preorder(A):
visit A
preorder(B)
preorder(C)
Visited nodes: A
48
• Visit A’s left subtree rooted at B
preorder(A): preorder(B):
visit A visit B
preorder(B) preorder(D)
preorder(C) preorder(E)
Visited nodes: A
49
• Visit B
preorder(A): preorder(B):
visit A visit B
preorder(B) preorder(D)
preorder(C) preorder(E)
Visited nodes: A B
50
• Visit B’s left subtree rooted at D
Visited nodes: A B
51
• Visit D
Visited nodes: A B D
52
• Visit D’s left subtree (empty)
preorder(None):
do nothing
Visited nodes: A B D
53
• Visit D’ left subtree, do nothing, return
preorder(None):
do nothing
Visited nodes: A B D
54
• Visit D’s right subtree rooted at H
preorder(H):
visit H
preorder(None)
preorder(None)
Visited nodes: A B D
55
• Visit H
preorder(H):
visit H
preorder(None)
preorder(None)
Visited nodes: A B D H
56
• Visit H’s left subtree (empty)
preorder(None): preorder(H):
do nothing visit H
preorder(None)
preorder(None)
Visited nodes: A B D H
57
• Visit H’s left subtree, do nothing, return
preorder(None): preorder(H):
do nothing visit H
preorder(None)
preorder(None)
Visited nodes: A B D H
58
• Visit H’s right subtree (empty)
preorder(H):
visit H
preorder(None): preorder(None)
do nothing preorder(None)
Visited nodes: A B D H
59
• Visit H’s right subtree, do nothing, return
preorder(H):
visit H
preorder(None): preorder(None)
do nothing preorder(None)
Visited nodes: A B D H
60
• Finished visiting the subtree rooted at H, return
preorder(H):
visit H
preorder(None)
preorder(None)
Visited nodes: A B D H
61
• Finished visiting the subtree rooted at D, return
Visited nodes: A B D H
62
• After finish visiting B’s left subtree rooted at D, continue to
visit the B’s right subtree rooted at E
preorder(A): preorder(B): preorder(E):
visit A visit B visit E
preorder(B) preorder(D) preorder(None)
preorder(C) preorder(E) preorder(None)
Visited nodes: A B D H
63
• Visit E
Visited nodes: A B D H E
64
• Visit E’s left subtree (empty). We omit this function call
here.
preorder(A): preorder(B): preorder(E):
visit A visit B visit E
preorder(B) preorder(D) preorder(None)
preorder(C) preorder(E) preorder(None)
Visited nodes: A B D H E
65
• Visit E’s right subtree (empty). We omit here this function
call.
preorder(A): preorder(B): preorder(E):
visit A visit B visit E
preorder(B) preorder(D) preorder(None)
preorder(C) preorder(E) preorder(None)
Visited nodes: A B D H E
66
• Finished visiting the subtree rooted at E, return
Visited nodes: A B D H E
67
• Finished visiting the subtree rooted at B, return
preorder(A): preorder(B):
visit A visit B
preorder(B) preorder(D)
preorder(C) preorder(E)
Visited nodes: A B D H E
68
• Finished visiting A’s left subtree rooted at B, continue to visit
the A’s right subtree rooted at C
preorder(A): preorder(C):
visit A visit C
preorder(B) preorder(F)
preorder(C) preorder(G)
Visited nodes: A B D H E
69
• Visit C
preorder(A): preorder(C):
visit A visit C
preorder(B) preorder(F)
preorder(C) preorder(G)
Visited nodes: A B D H E C
70
• Visit the subtree rooted at F
Visited nodes: A B D H E C
71
• Visit F
Visited nodes: A B D H E C F
72
• Visit F’s left subtree rooted at I
preorder(I):
visit I
preorder(None)
preorder(None)
Visited nodes: A B D H E C F
73
• Visit I
preorder(I):
visit I
preorder(None)
preorder(None)
Visited nodes: A B D H E C F I
74
• Visit I’s left subtree (empty). We omit here this function call
preorder(I):
visit I
preorder(None)
preorder(None)
Visited nodes: A B D H E C F I
75
• Visit I’s right subtree (empty). We omit here this function call
preorder(I):
visit I
preorder(None)
preorder(None)
Visited nodes: A B D H E C F I
76
• Finished visiting the subtree rooted at I, return
preorder(I):
visit I
preorder(None)
preorder(None)
Visited nodes: A B D H E C F I
77
• Finished visiting F’s left subtree rooted at I, continue to visit
F’s right subtree (empty). We omit this function call here.
preorder(A): preorder(C): preorder(F):
visit A visit C visit F
preorder(B) preorder(F) preorder(I)
preorder(C) preorder(G) preorder(None)
Visited nodes: A B D H E C F I
78
• Finished visiting the subtree rooted at F, return
Visited nodes: A B D H E C F I
79
• Finished visiting C’ left subtree rooted at F, continue to visit
C’s right subtree rooted at G
preorder(A): preorder(C): preorder(G):
visit A visit C visit G
preorder(B) preorder(F) preorder(None)
preorder(C) preorder(G) preorder(None)
Visited nodes: A B D H E C F I
80
• Visit G
Visited nodes: A B D H E C F I G
81
• Visit G’s left subtree (empty). We omit this function call
here.
preorder(A): preorder(C): preorder(G):
visit A visit C visit G
preorder(B) preorder(F) preorder(None)
preorder(C) preorder(G) preorder(None)
Visited nodes: A B D H E C F I G
82
• Visit G’s right subtree (empty). We omit this function call
here.
preorder(A): preorder(C): preorder(G):
visit A visit C visit G
preorder(B) preorder(F) preorder(None)
preorder(C) preorder(G) preorder(None)
Visited nodes: A B D H E C F I G
83
• Finished visiting the subtree rooted at G, return
Visited nodes: A B D H E C F I G
84
• Finished visiting the subtree rooted at C, return
preorder(A): preorder(C):
visit A visit C
preorder(B) preorder(F)
preorder(C) preorder(G)
Visited nodes: A B D H E C F I G
85
• Finished visiting the tree rooted at A, return.
• Preorder traversal finishes.
preorder(A):
visit A
preorder(B)
preorder(C)
Visited nodes: A B D H E C F I G
86
Example 2:
Iterative Implementation of Preorder Traversal
87
Iterative Preorder Traversal
B C
D E F G
89
Iterative Preorder Traversal
• Start at the root. Push the root A onto the stack.
B C
D E F G
90
Iterative Preorder Traversal
• Pop the node A from the stack, visit node A.
• Push A’s right child C onto the stack,
• Push A’s left child B onto the stack
A
B C
D E F G
B C
D E F G
B C
D E F G
B C
D E F G
B C
D E F G
B C
D E F G
B C
D E F G
B C
D E F G
B C
D E F G
Visited nodes: A B D H E C F I G
99
Iterative Preorder Traversal
• Stack is empty, finish.
B C
D E F G
Visited nodes: A B D H E C F I G
100
Tree Traversal:
Level-Order Traversal
101
Level Order Traversal
102
Level Order Traversal
A
B C
D E F G
H I
103
Level Order Traversal
• Queue is needed for implementing level order
traversal
• For example, in the level order traversal shown below,
1) when we visit node B, before visiting node C, we need to
store node B’s children node D and E so that we can visit
these two nodes later.
2) when we visit node C, before visiting node D, we need to
store node C’s children node F and G.
3) we notice that we now stored nodes D, E, F, G, and we will
visit these nodes in the order of D, E, F and G. It is First-in-
first-out, so queue is needed
104
Level Order Traversal: Iterative
B C
D E F G
H I
106
Level Order Traversal
B C
D E F G
107
Level Order Traversal
• Start at the root. Enqueue the root A
B C
D E F G
108
Level Order Traversal
• Dequeue node A from queue, and visit node A
• Enqueue the children of A
B C
D E F G
B C
D E F G
B C
D E F G
B C
D E F G
B C
D E F G
B C
D E F G
B C
D E F G
B C
D E F G
B C
D E F G
B C
D E F G
120
Recursion vs. Iteration
124
Summary
• Tree is useful for storing the data that naturally form hierarchy (such
as file system, decision tree)
• The binary search tree and AVL tree (will learn later) are useful for
storing and searching dynamic data
• Tree Traversal
• Depth-first traversal
• Preorder, Inorder, Postorder traversal
• Implemented using recursive function or stack
• Breath-first traversal
• Level-order traversal
• Implemented using queue
• From the implementations of traversal, we realize that it is
important to choose the proper data structure when we solve a
computational problem; otherwise, it may be extremely difficult
(sometimes impossible) to develop the algorithm.
125
Programming Practice on Binary Tree
126