Binary Trees
Binary Trees
Outline
Tree Stuff
Trees
Binary Trees
Implementation of a Binary Tree
Tree Traversals – Depth First
Preorder
Inorder
Postorder
Breadth First Tree Traversal
Binary Search Trees
Tree Stuff
Trees:
Another Abstract Data Type
Data structure made of nodes and pointers
Much like a linked list
The difference between the two is how they are
organized.
A linked list represents a linear structure
A predecessor/successor relationship between the
nodes of the list
A tree represents a hierarchical relationship
between the nodes (ancestral relationship)
A node in a tree can have several successors, which
we refer to as children
A nodes predecessor would be its parent
Tree Stuff
Trees:
General Tree Information:
Top node in a tree is called the root
the root node has no parent above because it’s the
root!
Every node in the tree can have “children”
nodes
Each child node can, in turn, be a parent to its
children and so on
Nodes having no children are called leaves
Any node that is not a root or a leaf is an
interior node
The height of a tree is defined to be the
length of the longest path from the root to a
leaf in that tree.
Tree Stuff
Trees:
Here’s a picture of a tree:
2 is the root
2, 5, 11, and 4 are leaves
7, 5, 6, and 9 are interiornodes
Tree Stuff
Binary Trees:
A tree in which each node can have a
maximum of two children
Each node can have no child, one child, or two
children
And a child can only have one parent
Pointers help us to identify if it is a right child or
a left oneof
Examples
two
Binary Trees:
Tree Stuff
Examples of trees that are NOT Binary
Trees:
Tree Stuff
More Binary Tree Goodies:
A full binary tree:
Every node, other than the leaves, has two
children
a
b c
d e g, h, e, and c
are leaves: so
g h they have no
children.
Tree Stuff
More Binary Tree Goodies:
A complete binary tree:
Every level, except possibly the last, is
completely filled, and all nodes are as far left
as possible.
Tree Stuff
More Binary Tree Goodies:
The root of the tree is at level 0
The level of any other node in the tree is
one more than the level of its parent
Total # of nodes (n) in acomplete binary
tree:
n = 2h+1 – 1 (maximum)
Height (h) of the tree:
h = log((n + 1)/2)
If we have 15 nodes
h = log(16/2) = log(8) = 3
Tree Stuff
Implementation of a Binary Tree:
A binary tree has a natural
implementation using linked storage
Each node of a binary tree has both left
and right subtrees that can be reached
with pointers:
struct tree_node { left_child data
int data;
right_child
struct tree_node *left_child;
struct tree_node *right_child;
}
Tree Traversals
Traversal of Binary Trees:
We need a way of zipping through a tree for
searching, inserting, etc.
But how can we do this?
If you remember…
Linked lists are traversed from the head to the last
node
…sequentially
b c
abc
Tree Traversals - Preorder
Preorder Traversal – Example 2
a
b c
f
d e
g h i j
b c
bac
Tree Traversals - Inorder
Inorder Traversal – Example 2
a
b c
f
d e
g h i j
b c
bc a
Tree Traversals – Postorder
Postorder Traversal – Example 2
a
b c
f
d e
g h i j
A A breadth-first search
(BFS) explores nodes
nearest the root before
B C exploring nodes further
away
D E F G For example, after
searching A, then B, then
C, the search proceeds
H I J K
with D, E, F, G
Node are explored in the
L M N O P Q order A B C D E F G H I J K L M
NOPQ
J will be found before N
Breadth-First Traversal
H
D L
B F J N
A C E G I K M O
O M K I G E C A N J F B L D H
Breadth-First Traversal
Coding the Breadth-First Traversal
Let’s say you want to Traverse and Print all
nodes?
Think about it, how would you make this happen?
SOLUTION:
Enqueue the root node.
while (more nodes still in queue) {
Dequeue node at front (of queue)
Print this node (that we just dequeued)
Enqueue its children (if applicable): left then
right
…continue till no more nodes in queue
}
Binary Search Tree
Binary Search Trees
We’ve seen how to traverse binary trees
But it is not quite clear how this data
structure helps us
What is the purpose of binary trees?
What if we added a restriction…
Consider the followingbinary tree:
What pattern can you see?
Binary Search Tree
Binary Search Trees
What pattern can you see?
For each node N, all the values stored in the left
subtree of N are LESS than the value stored in N.
Also, all the values stored in the right subtree of N
are GREATER than the value stored in N.
Why might this property be a desireable one?
Searching for a node is super fast!
Normally, if we search through n nodes, it takes
O(n) time
But notice what is going on here:
This ordering property of the tree tells us where to
search
We choose to look to the left OR …O(log
look to the
n) right of a
node time
Binary Search Tree
Binary Search Trees
Details:
ALL of the data values in the left subtree of each
node are smaller than the data value in the node
itself (root of said subtree)
Stated another way, the value of the node itself is
larger than the value of every node in its left subtree.
ALL of the data values in the right subtree of each
node are larger than the data value in the node
itself (root of the subtree)
Stated another way, the value of the node itself is
smaller than the value of every node in its right
subtree.
Both the left and right subtrees, of any given node,
are themselves binary search trees.
Binary Search Tree
4
4
2 6
4 5
2 3 5 8
0 6 6 8
1 2 4 6
5 8 0 2
8 1 3 4 5 6
9 0 2 8 4
1)
Step 1:
Create a new node with
value 10
Insert node into tree
The tree is currently empty
New node becomes the root
Binary Search Tree:
Insertion
Insertion into a Binary Search Tree
10, 14, 6, 2, 5, 15, and 17
Step 2: 1
Create a new node with value 14 0
This node belongs in the right
1
subtree of node 10 4
Since 14 > 10
The right subtree of node 10 is
empty
So node 14 becomes the
right child of node 10
Binary Search Tree:
Insertion
Insertion into a Binary Search Tree
10, 14, 6, 2, 5, 15, and 17
Step 3: 1
Create a new node with value 6 0
This node belongs in the left
6 1
subtree of node 10 4
Since 6 < 10
The left subtree of node 10 is
empty
So node 6 becomes the left
child of node 10
Binary Search Tree:
Insertion
Insertion into a Binary Search Tree
10, 14, 6, 2, 5, 15, and 17
Step 4: 1
Create a new node with value 2 0
This node belongs in the left
6 1
subtree of node 10 4
Since 2 < 10
The root of the left subtree is 6 2
The new node belongs in the left
subtree of node 6
Since 2 < 6
So node 2 becomes the left child
of node 6
Binary Search Tree:
Insertion
Insertion into a Binary Search Tree
10, 14, 6, 2, 5, 15, and 17
Step 5: 1
Create a new node with value 5 0
This node belongs in the left
6 1
subtree of node 10 4
Since 5 < 10
The new node belongs in the left 2
subtree of node 6
Since 5 < 6
5
And the new node belongs in the
right subtree of node 2
Since 5 > 2
Binary Search Tree:
Insertion
Insertion into a Binary Search Tree
10, 14, 6, 2, 5, 15, and 17
Step 6: 1
Create a new node with value 15 0
This node belongs in the right
6 1
subtree of node 10 4
Since 15 > 10
The new node belongs in the 2 1
right subtree of node 14 5
Since 15 > 14
5
The right subtree of node 14 is
empty
So node 15 becomes right child
of node 14
Binary Search Tree:
Insertion
Insertion into a Binary Search Tree
10, 14, 6, 2, 5, 15, and 17
Step 7: 1
Create a new node with value 17 0
This node belongs in the right
6 1
subtree of node 10 4
Since 17 > 10
The new node belongs in the 2 1
right subtree of node 14 5
Since 17 > 14
5 1
And the new node belongs in the 7
right subtree of node 15
Since 17 > 15
Binary Search Tree:
Insertion
Insertion into a Binary Search Tree
In main, we have the following:
struct tree_node *my_root=NULL, *temp_node;
// ***************
// OTHER CODE HERE
// ***************
While (something_here) {
printf("What value would you like to insert?");
scanf("%d", &val);
temp_node = create_node(val); // Create the node.
// Insert the value.
my_root = insert(my_root, temp_node);
// more code
Binary Search Tree:
Insertion
Insertion into a Binary Search Tree
Here’s our basic plan to do this recursively:
1) If the tree is empty, just return a pointer to a
node containing the new value
cuz this value WILL be the ROOT
2) Otherwise, see which subtree the node should be
inserted into
How?
Compare the value to insert with the value stored at
the root.
3) Based on this comparison, recursively either
insert into the right subtree, or into the left
subtree.
Binary Search Tree:
Insertion
Insertion into a Binary Search Tree
And here’s the matching code:
struct tree_node* insert(struct tree_node *root, struct tree_node *element) {
// Inserting into an empty tree.
if (root == NULL)
return element;
else {
// element should be inserted to the right.
if (element->data > root->data)
root->right = insert(root->right, element);
// element should be inserted to the left.
else
root->left = insert(root->left, element);
// Finally, return the root pointer of the updated tree.
return root;
}
}
Binary Search Tree: Creation
1 1
0 0
6 1 6 1
4 4
4 8 1 1 4 8 1
2 8 8
2 1 2 1
6 6
Initial BST with BST after deletion of
node 12 marked for node 12
deletion
Binary Trees: Deletion
Deleting a Leaf Node
This one is pretty easy
We start by identifying the parent of the
node we wish to delete
Which we actually do in ALL three cases
We then free that node, accessing it via
parent:
free(parent->left) or
free(parent->right)
Now we need to simply update the parent’s
left or right pointer, signifying that the
parent no longer has that child
Binary Trees: Deletion
Deleting a Leaf Node
This one is pretty easy
We start by identifying the parent of the
node we wish to delete
Which we actually do in ALL three cases
Just set the appropriate node to NULL:
parent->left = NULL or
parent->right = NULL
So now instead of pointing to the
toBeDeleted node
The parent simply points to NULL
Binary Trees: Deletion
Deleting a Node with One Child
This one is also not too complicated
But does require more thought than deleting a
leaf node
Again, we start by finding the parent
meaning, the parent of the node we want to
delete
The parent’s pointer to the node is
changed to now point to the deleted
node’s child
This has the effect of lifting up the deleted
nodes child by one level in the tree
All great-great-…-great-grandchildren will lose
Binary Trees: Deletion
Deleting a Node with One Child
parent->left = parent->left->left;
1 1
0 0
6 1 6 1
4 4
4 8 1 1 2 8 1 1
2 8 2 8
2 1 1
6 6
Initial BST with node BST after deletion of node
4 marked for deletion 4. Node 2 has taken the
place of the deleted node
Binary Trees: Deletion
Deleting a Node with One Child
The previous example illustrated when we
delete a left node that has a left child
Notice that it makes no difference whether
the only child is a left child or a right child
The next example illustrated when we
delete a right node that has a right
child
Again, the deletion simply lifts up the subtree of
the deleted node by one level
The other possibilities is a left node that
has a right child or a right node that has a
left child
Binary Trees: Deletion
Deleting a Node with One Child
parent->right = parent->right->right;
1 1
0 0
6 1
6 1 8
4
4 8 1
4 8 1 6
8
1 1
2 1 2 7
5
6
Initial BST with node 14 1 BST after deletion of node 14. Node
1
marked for deletion 5 7 18 has taken the place of the deleted
node and the entire subtree moved
up one level.
d
a c
Deleting a Node with two children
This is the scenario that requires a bit of
thought
If we wish to delete node b (example above)
We can’t just raise up b’s children
since node d can’t use its left pointer to point to
more than one child
d‘s left can’t point to both node a and node c
So think about what we need to do in
order to maintain the structure (and
ordering property)
Binary Trees: Deletion
Deleting a Node with two children
Consider this example tree
We want to delete node 18
Ask yourself:
What two nodes could I replacethe 18 with and
5
still maintainthe binary search tree property?
9
1 6
8 7
1 3 6 7
3 2 3 2
1 1 2 4
0 5 5 3
5
9
Remember:
All the nodes to the left of 18 MUST be smaller
than 18
All the nodes right of 18 MUST be greater than
18
Thus, if we delete 18
there are only two nodes we could put at 18’s
position without causing serious repercussions:
The maximum value in the left subtree of
node 18
Which is 15
The minimum value in the right subtree of
node 18
5
9
Thus, if we delete 18
There are two possible nodes that could go into
18’s position:
Node 15 (greatest value in left subtree)
Node 25 (smallest value in right subtree)
We simply pick one of these to put at 18’s
position
We essentially copy the node to 18’s position
Then we have to delete the actual node that we
just copied
Meaning, if we copy node 15 into 18’s positon
We will have two 15s
So we now need to delete the leaf node 15
5
9
1 6 1 6
8 7 8 7
1 3 6 7 1 3 6 7
3 2 3 2 3 2 3 2
1 1 2 4 1 1 2 4
0 5 5 3 0 5 5 3
Initial BST with node 18 marked This node contains the logical
for deletion. Note that this predecessor of the node to be
node has two children with deleted. Note that it is the greatest
values 13 and 32. node in the left subtree of the node
to be deleted.
Binary Trees: Deletion
Deleting a Node with two children
(example) 5 5
9 9
1 6 1 6
8 7 8 7
1 3 6 7 1 3 6 7
3 2 3 2 3 2 3 2
1 1 2 4 1 1 2 4
0 5 5 3 0 5 5 3
Initial BST with node 18 marked This node contains the logical
for deletion. Note that this successor of the node to be deleted.
node has two children with Note that it is the smallest node in
values 13 and 32. the right subtree of the node to be
deleted.
Binary Trees: Deletion
Deleting a Node with two children
(example) 5 5
9 9
1 6 1 6
8 7 5 7
1 3 6 7 1 3 6 7
3 2 3 2 3 2 3 2
1 1 2 4 1 2 4
0 5 5 3 0 5 3
This node contains the logical The BST after the deletion of
predecessor of the node to be node 18 using the
deleted. Note that it is the greatest replacement by the logical
node in the left subtree of the node predecessor node.
to be deleted.
Binary Trees: Deletion
Deleting a Node with two children
(example) 5 5
9 9
1 6 2 6
8 7 5 7
1 3 6 7 1 3 6 7
3 2 3 2 3 2 3 2
1 1 2 4 1 1 4
0 5 5 3 0 5 3
This node contains the logical The BST after the deletion of
successor of the node to be deleted. node 18 using the
Note that it is the smallest node in replacement by the logical
the right subtree of the node to be successor node.
deleted.
Binary Trees: Deletion
Deleting a Node with two children
For the previous example,
The nodes that we copied to 18’s position were
both leaf nodes
How did this help?
Once copied over, we need to delete those nodes
Since they are leaves, this process is easy
But what if they are not leaf nodes?
Meaning, they have one child
Remember, we are guaranteed that they have AT MOST
one kid
It is still easy!
We would simply be deleting a node with one child
Which simply “lifts” up that subtree one level
Binary Trees: Deletion
Deleting a Node with two children
There’s a lot going on for deletion
So when you examine the code,
You will see many auxiliary functions used, such
as:
findNode: returns a pointer to a node in a given tree that
stores a particular value
parent: finds the parent of a given node in a given binary
tree
minVal: finds the minimum value in a given binary tree
maxVal: finds the maximum value in a given binary tree
isLeaf: determines if a node is a leaf node or not
hasOnlyLeftChild: determines if a node ONLY has a left
child
hasOnlyRightChild: determines if a node ONLY has right
kid
Binary Trees: Deletion
Auxiliary functions:
findNode: returns a pointer to a node in a
given tree that stores a particular value
The first step in deletion is finding the node in
the tree
This is basically the search function from last
time
The arguments to the function are:
A pointer to the root of some tree (or subtree)
The value we are searching for
IF found, the function returns a pointer to the
node
Else, NULL is returned
Binary Trees: Deletion
Auxiliary functions:
findNode: returns a pointer to a node in a
given tree that stores a particular value
struct tree_node* findNode(struct tree_node *current_ptr, int value) {
if (current_ptr != NULL) {
// Found the value at the root.
if (current_ptr->data == value)
return current_ptr;
// Search to the left.
if (value < current_ptr->data)
return findNode(current_ptr->left, value);
// Or...search to the right.
else
return findNode(current_ptr->right, value);
}
else
return NULL; // No node found.
}
Binary Trees: Deletion
Auxiliary functions:
parent: finds the parent of a given node in
a given binary tree
Remember: we need to know the parent of the
node we wish to delete
This allows us to modify the left/right pointers of
the parent, effectively removing the child node
The arguments to the function are:
1) The root of the tree
2) A pointer to the node we want to find the parents of
If found, a pointer to the parent node is returned
Binary Trees: Deletion
Auxiliary functions:
parent: finds the parent of a given node in
a given binary tree
struct tree_node* parent(struct tree_node *root, struct tree_node *node) {
// Take care of NULL cases.
if (root == NULL || root == node)
return NULL;
// The root is the direct parent of node.
if (root->left == node || root->right == node)
return root;
// Look for node's parent in the left side of the tree.
if (node->data < root->data)
return parent(root->left, node);
// Look for node's parent in the right side of the tree.
else if (node->data > root->data)
return parent(root->right, node);
return NULL; // Catch any other extraneous cases.
}
Binary Trees: Deletion
Auxiliary functions:
minVal: finds the minimum value in a given
binary tree
Remember: when we delete a node with two
children
We need to replace that node with either:
The minimum value in the right subtree, or
The maximum value in the left subtree
The argument to the function is the root of the
tree
The function simply returns a pointer to the node
containing the minimum value
Binary Trees: Deletion
Auxiliary functions:
minVal: finds the minimum value in a given
binary tree
Remember:
The minimum value in a given binary tree will either
be the root OR it will be found in the left subtree
Practice Tree #1 1 2
Solutions on page 3 8
33
2 9 1 3
2 5 6
7 1
3 5 0 7 4
1 3 4
9
2 1 8 6 6
6 4 7 3 9
5 7 1 8 5 5 6
4 1 1 6 9 8
Binary Tree Traversals – Practice
Problems 3
2 1 Practice Tree #2
8 3
Solutions on Page
34
3 1 9 2
6 5 2
1 7
4 7 0 5 3
4 3 1
9
6 6 8 1 2
9 3 7 4 6
6 5 5 8 1 7 5
8 9 6 1 1 4
Practice Problem Solutions –
Tree #1
Preorder Traversal:
3, 13, 22, 19, 26, 54, 71, 33, 14, 11, 87, 8, 56, 9, 75, 28, 15, 10,
63, 36, 7, 69, 59, 68, 44
Inorder Traversal:
54, 26, 71, 19, 22, 11, 14, 33, 8, 87, 56, 13, 9, 75, 3, 63, 10, 15,
28, 59, 69, 68, 7, 36, 44
Postorder Traversal:
54, 71, 26, 19, 11, 14, 8, 56, 87, 33, 22, 75, 9, 13, 63, 10, 15, 59,
68, 69, 7, 44, 36, 28, 3
Practice Problem Solutions –
Tree #2
Preorder Traversal:
3, 28, 36, 44, 7, 69, 68, 59, 15, 10, 63, 13, 9, 75, 22, 33, 87, 56,
8, 14, 11, 19, 26, 71, 54
Inorder Traversal:
44, 36, 7, 68, 69, 59, 28, 15, 10, 63, 3, 75, 9, 13, 56, 87, 8, 33,
14, 11, 22, 19, 71, 26, 54
Postorder Traversal:
44, 68, 59, 69, 7, 36, 63, 10, 15, 28, 75, 9, 56, 8, 87, 11, 14, 33,
71, 54, 26, 19, 22, 13, 3