1. Traversing a Binary Tree without recursion
In-order Traversal
Pre-order Traversal
Post-order Traversal
2. The Scenario
• Imagine we have a binary tree
• We want to traverse the tree
– It’s not linear
– We need a way to visit all nodes
• Three things must happen:
– Deal with the entire left sub-tree
– Deal with the current node
– Deal with the entire right sub-tree
In-order Traversal
3. Use the Activation Stack
• With a recursive module, we
can make use of the
activation stack to visit the
sub-trees and “remember”
where we left off.
13
9
2
42
4. Use the Activation Stack
• With a recursive module, we
can make use of the
activation stack to visit the
sub-trees and “remember”
where we left off.
13
9
2
42
At 13 – do left
5. Use the Activation Stack
• With a recursive module, we
can make use of the
activation stack to visit the
sub-trees and “remember”
where we left off.
13
9
2
42
At 13 – do left
At 9 – do left
6. Use the Activation Stack
• With a recursive module, we
can make use of the
activation stack to visit the
sub-trees and “remember”
where we left off.
13
9
2
42
At 13 – do left
At 9 – do left
At 2 – do left
7. Use the Activation Stack
• With a recursive module, we
can make use of the
activation stack to visit the
sub-trees and “remember”
where we left off.
13
9
2
42
At 13 – do left
At 9 – do left
At 2 – do left
At NIL
8. Use the Activation Stack
• With a recursive module, we
can make use of the
activation stack to visit the
sub-trees and “remember”
where we left off.
13
9
2
42
At 13 – do left
At 9 – do left
At 2 – do current
9. Use the Activation Stack
• With a recursive module, we
can make use of the
activation stack to visit the
sub-trees and “remember”
where we left off.
13
9
2
42
At 13 – do left
At 9 – do left
At 2 – do right
10. Use the Activation Stack
• With a recursive module, we
can make use of the
activation stack to visit the
sub-trees and “remember”
where we left off.
13
9
2
42
At 13 – do left
At 9 – do left
At 2 – do right
At NIL
11. Use the Activation Stack
• With a recursive module, we
can make use of the
activation stack to visit the
sub-trees and “remember”
where we left off.
13
9
2
42
At 13 – do left
At 9 – do left
At 2 - done
12. Use the Activation Stack
• With a recursive module, we
can make use of the
activation stack to visit the
sub-trees and “remember”
where we left off.
13
9
2
42
At 13 – do left
At 9 – do current
13. Use the Activation Stack
• With a recursive module, we
can make use of the
activation stack to visit the
sub-trees and “remember”
where we left off.
13
9
2
42
At 13 – do left
At 9 – do right
14. Use the Activation Stack
• With a recursive module, we
can make use of the
activation stack to visit the
sub-trees and “remember”
where we left off.
13
9
2
42
At 13 – do left
At 9 – do right
At NIL
15. Use the Activation Stack
• With a recursive module, we
can make use of the
activation stack to visit the
sub-trees and “remember”
where we left off.
13
9
2
42
At 13 – do left
At 9 – done
16. Use the Activation Stack
• With a recursive module, we
can make use of the
activation stack to visit the
sub-trees and “remember”
where we left off.
13
9
2
42
At 13 – do current
17. Use the Activation Stack
• With a recursive module, we
can make use of the
activation stack to visit the
sub-trees and “remember”
where we left off.
13
9
2
42
At 13 – do right
18. Use the Activation Stack
• With a recursive module, we
can make use of the
activation stack to visit the
sub-trees and “remember”
where we left off.
13
9
2
42
At 13 – do right
At 42 – do left
19. Use the Activation Stack
• With a recursive module, we
can make use of the
activation stack to visit the
sub-trees and “remember”
where we left off.
13
9
2
42
At 13 – do right
At 42 – do left
At NIL
20. Use the Activation Stack
• With a recursive module, we
can make use of the
activation stack to visit the
sub-trees and “remember”
where we left off.
13
9
2
42
At 13 – do right
At 42 – do current
21. Use the Activation Stack
• With a recursive module, we
can make use of the
activation stack to visit the
sub-trees and “remember”
where we left off.
13
9
2
42
At 13 – do right
At 42 – do right
22. Use the Activation Stack
• With a recursive module, we
can make use of the
activation stack to visit the
sub-trees and “remember”
where we left off.
13
9
2
42
At 13 – do right
At 42 – do right
At NIL
23. Use the Activation Stack
• With a recursive module, we
can make use of the
activation stack to visit the
sub-trees and “remember”
where we left off.
13
9
2
42
At 13 – do right
At 42 – done
24. Use the Activation Stack
• With a recursive module, we
can make use of the
activation stack to visit the
sub-trees and “remember”
where we left off.
13
9
2
42
At 13 – done
25. Outline of In-Order Traversal
• Three principle steps:
– Traverse Left
– Do work (Current)
– Traverse Right
37. Finding the Correct Location
• Must maintain “search” structure
– Everything to left is less than current
– Everything to right is greater than current
• Adding at the “bottom” guarantees
we keep search structure.
• We’ll recurse to get to the “bottom”
(i.e. when current = nil)
38. Finding the Correct Location
if (current = nil)
DO “ADD NODE” WORK HERE
elseif (current^.data > value_to_add) then
// recurse left
Insert(current^.left, value_to_add)
else
// recurse right
Insert(current^.right, value_to_add)
endif
39. Adding the Node
• Current is an in/out pointer
– We need information IN to evaluate current
– We need to send information OUT because
we’re changing the tree (adding a node)
• Once we’ve found the correct location:
– Create a new node
– Fill in the data field
(with the new value to add)
– Make the left and right pointers point to nil
(to cleanly terminate the tree)
40. Adding the Node
current <- new(Node)
current^.data <- value_to_add
current^.left <- nil
current^.right <- nil
41. The Entire Module
procedure Insert(cur iot in/out Ptr toa Node,
data_in iot in num)
if(cur = NIL) then
cur <- new(Node)
cur^.data <- data_in
cur^.left <- NIL
cur^.right <- NIL
elseif(cur^.data > data_in)
Insert(cur^.left, data_in)
else
Insert(cur^.right, data_in)
endif
endprocedure // Insert
42. Tracing Example
The following example shows a trace of
the BST insert.
• Begin with an empty BST (a pointer)
• Add elements 42, 23, 35, 47 in the
correct positions.
43. Head iot Ptr toa Node
head <- NIL
Insert(head, 42)
44. Head iot Ptr toa Node
head <- NIL
Insert(head, 42)
head
45. Head iot Ptr toa Node
head <- NIL
Insert(head, 42)
head
46. Head iot Ptr toa Node
head <- NIL
Insert(head, 42)
head
47. Head iot Ptr toa Node
head <- NIL
Insert(head, 42)
procedure Insert(
cur iot in/out Ptr toa Node,
data_in iot in num)
if(cur = NIL) then
cur <- new(Node)
cur^.data <- data_in
cur^.left <- NIL
cur^.right <- NIL
elseif(cur^.data > data_in)
Insert(cur^.left, data_in)
else
Insert(cur^.right, data_in)
endif
endprocedure // Insert
head
48. Head iot Ptr toa Node
head <- NIL
Insert(head, 42)
procedure Insert(
cur iot in/out Ptr toa Node,
data_in iot in num)
if(cur = NIL) then
cur <- new(Node)
cur^.data <- data_in
cur^.left <- NIL
cur^.right <- NIL
elseif(cur^.data > data_in)
Insert(cur^.left, data_in)
else
Insert(cur^.right, data_in)
endif
endprocedure // Insert
head
49. Head iot Ptr toa Node
head <- NIL
Insert(head, 42)
procedure Insert(
cur iot in/out Ptr toa Node,
data_in iot in num)
if(cur = NIL) then
cur <- new(Node)
cur^.data <- data_in
cur^.left <- NIL
cur^.right <- NIL
elseif(cur^.data > data_in)
Insert(cur^.left, data_in)
else
Insert(cur^.right, data_in)
endif
endprocedure // Insert
head
42
50. Head iot Ptr toa Node
head <- NIL
Insert(head, 42)
procedure Insert(
cur iot in/out Ptr toa Node,
data_in iot in num)
if(cur = NIL) then
cur <- new(Node)
cur^.data <- data_in
cur^.left <- NIL
cur^.right <- NIL
elseif(cur^.data > data_in)
Insert(cur^.left, data_in)
else
Insert(cur^.right, data_in)
endif
endprocedure // Insert
head
42
51. Head iot Ptr toa Node
head <- NIL
Insert(head, 42)
procedure Insert(
cur iot in/out Ptr toa Node,
data_in iot in num)
if(cur = NIL) then
cur <- new(Node)
cur^.data <- data_in
cur^.left <- NIL
cur^.right <- NIL
elseif(cur^.data > data_in)
Insert(cur^.left, data_in)
else
Insert(cur^.right, data_in)
endif
endprocedure // Insert
head
42
52. Head iot Ptr toa Node
head <- NIL
Insert(head, 42)
procedure Insert(
cur iot in/out Ptr toa Node,
data_in iot in num)
if(cur = NIL) then
cur <- new(Node)
cur^.data <- data_in
cur^.left <- NIL
cur^.right <- NIL
elseif(cur^.data > data_in)
Insert(cur^.left, data_in)
else
Insert(cur^.right, data_in)
endif
endprocedure // Insert
head
42
92. Summary
• Preserve “search” structure!
• Inserting involves 2 steps:
– Find the correct location
• For a BST insert, always insert at the
“bottom” of the tree
– Do commands to add node
• Create node
• Add data
• Make left and right pointers point to nil
94. The Scenario
• We have a Binary Search Tree and
want to remove some element based
upon a match.
• Must preserve “search” property
• Must not lose any elements (i.e. only
remove the one element)
95. BST Deletion
• Search for desired item.
• If not found, then return NIL or print error.
• If found, perform steps necessary to
accomplish removal from the tree.
96. Four Cases for Deletion
• Delete a leaf node
• Delete a node with only one child (left)
• Delete a node with only one child (right)
• Delete a node with two children
Cases 2 and 3 are comparable and only
need slight changes in the conditional
statement used
97. Delete a Leaf Node
Simply use an “in/out”
pointer and assign it
to “nil”. This will
remove the node from
the tree.
cur <- nil
14
50
94
9 71 116
108
66
13
42
98. Delete a Leaf Node
Simply use an “in/out”
pointer and assign it
to “nil”. This will
remove the node from
the tree.
cur <- nil
Let’s delete 42.
14
50
94
9 71 116
108
66
13
42
99. Delete a Leaf Node
Simply use an “in/out”
pointer and assign it
to “nil”. This will
remove the node from
the tree.
cur <- nil
Move the pointer;
now nothing points
to the node.
14
50
94
9 71 116
108
66
13
42
100. Delete a Leaf Node
Simply use an “in/out”
pointer and assign it
to “nil”. This will
remove the node from
the tree.
cur <- nil
The resulting tree.
14
50
94
9 71 116
108
66
13
101. Delete a Node with One Child
Use an “in/out” pointer.
Determine if it has a left
or a right child.
Point the current
pointer to the
appropriate child:
cur <- cur^.left_child
or
cur <- cur^.right_child
14
50
94
71 116
108
66
42
102. Delete a Node with One Child
Use an “in/out” pointer.
Determine if it has a left
or a right child.
Point the current
pointer to the
appropriate child:
cur <- cur^.left_child
or
cur <- cur^.right_child
Let’s delete 14.
14
50
94
71 116
108
66
42
103. Delete a Node with One Child
Use an “in/out” pointer.
Determine if it has a left
or a right child.
Point the current
pointer to the
appropriate child:
cur <- cur^.right_child
Move the pointer; now
nothing points to the
node.
14
50
94
71 116
108
66
42
104. Delete a Node with One Child
Use an “in/out” pointer.
Determine if it has a left
or a right child.
Point the current
pointer to the
appropriate child:
cur <- cur^.right_child
The resulting tree.
50
94
71 116
108
66
42
105. Delete a Node with One Child
Use an “in/out” pointer.
Determine if it has a left
or a right child.
Point the current
pointer to the
appropriate child:
cur <- cur^.left_child
or
cur <- cur^.right_child
Let’s delete 71.
14
50
94
71 116
108
66
42
106. Delete a Node with One Child
Use an “in/out” pointer.
Determine if it has a left
or a right child.
Point the current
pointer to the
appropriate child:
cur <- cur^.left_child
Move the pointer; now
nothing points to the
node.
14
50
94
71 116
108
66
42
107. Delete a Node with One Child
Use an “in/out” pointer.
Determine if it has a left
or a right child.
Point the current
pointer to the
appropriate child:
cur <- cur^.left_child
The resulting tree.
14
50
94
116
108
66
42
108. Delete a Node with Two Children
14
50
94
71 116
108
66
42
Let’s delete 94.
109. Delete a Node with Two Children
14
50
94
71 116
108
66
42
Look to the right
sub-tree.
110. Delete a Node with Two Children
14
50
94
71 116
108
66
42
Find and copy the
smallest value
(this will erase the
old value but creates
a duplicate).
108
111. 108
Delete a Node with Two Children
14
50
71 116
108
66
42
The resulting tree
so far.
112. 108
Delete a Node with Two Children
14
50
71 116
108
66
42
Now delete the
duplicate from
the left sub-tree.
113. Delete a Node with Two Children
14
50
71 116
66
42
The final resulting
tree – still has search
structure.
108