06-1 BinaryTrees
06-1 BinaryTrees
Binary Trees
(Java)
Outlin
e
Tree Stuff
Trees
Binary Trees
Implementation of a Binary Tree
Examples of 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 they
g h 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 a
complete 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:
}
Tree Traversals – Depth
First
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
Can’t we just “do that” for binary trees.?.
NO! There is no such natural linear ordering for nodes
of a tree.
Turns out, there are THREE ways/orderings of
traversing a binary tree:
Preorder, Inorder, and Postorder
Tree Traversals – Depth
First
A depth-first search (DFS)
A
explores a path all the way to
a leaf before backtracking and
B C exploring another path
For example, after searching
A, then B, then D, the search
D E F G
backtracks and tries another
path from B
H I
J K ◼ Node are
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
bca
Tree Traversals –
Postorder
◼ Postorder Traversal – Example 2
a
b c
f
d e
g h i j
Practice Tree #1
13 28
Solutions on slide 27
22 9 15 36
75 10
33 7 44
19
26 14 87 63 69
54 71 11 8 56 59 68
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
Breadth-First
Traversal
A A breadth-first search (BFS)
explores nodes nearest the
root before exploring nodes
B C
further away
For example, after Searching A,
D E F G then B, then C, the search
proceeds with D, E, F, G
Node are explored in the order A B
H I J K CDEFGHIJKLM NOPQ
J will be found before N
L M N O P Q
Breadth-First
Traversal
H
D L
B F J N
A C E G I K M O
H D L B F J N A C E G I K M O
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:
2)
1) while (more nodes
Enqueue stillnode.
the root 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
}
Breadth-First Traversal- implementation
public static void traverseBinaryTree(Node root) {
if (root == null) {
System.out.println("Tree is empty");
return;
}
Queue queue = new Queue();
queue.enqueue(root);
while (!queue.isEmpty()) {
Node node = queue.dequeue();
System.out.println(node.data);
if (node.left != null) {
queue.enqueue(node.left);
}
if (node.right != null) {
queue.enqueue(node.right);
}
}
}
Search & Insert
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 following
binary tree:
24 65
20 36 56 88
15 28 40 62
8 19 30 42 58 64
A Binary Search
Tree
Binary Search Tree: Searching
◼ Binary Search Trees
◼ Searching for a node:
◼ Algorithm:
1) IF the tree is NULL, return false.
ELSE
2) Check the root node. If the value we are
searching for is in the root, return 1 (representing
“found”).
3) If not, if the value is less than that stored in the root
node, recursively search in the left subtree.
4) Otherwise, recursively search in the right subtree.
Binary Search Tree: Searching
◼ Here is the search method:
if (data == p.data) {
return(true);
}
else if (data < p.data)
{ return(recursiveSearch(p.left,
data));
}
else {
return(recursiveSearch(p.right, data));
}
}
Binary Search Tree: Search
Search of an Arbitrary Binary Tree
We’ve seen how to search for a node in a binary
search tree
Now consider the problem if the tree is NOT a
binary search tree
It does not have the ordering property
You could simply perform one of the traversal
methods, checking each node in the process
Unfortunately, this won’t be O(log n) anymore
It degenerates to O(n) since we possibly check all
nodes
The following slide shows another way to do
Binary Search Tree: Searching
◼ Search of an Arbitrary Binary Tree:
◼ The whole purpose here is to be comfortable with
trees and binary search trees
boolean searchTree(int data)
{ return(searchTree(root,
data));
}
if (psearchTree(intBSTnode
boolean == null) { // meaning,
p, there is no node!
return(false);
int data) {
}
if (data == p.data){
return(true);
}
return
(searchTree(p.left,
data) ||
searchTree(p.right,
Binary Search Tree: Creation
Insertion into a Binary Search Tree
Before we can insert a node into a BST, what is
the one obvious thing that we must do?
We have to actually create the node that we want
to insert
◼ And save appropriate data value(s) into it
Binary Search Tree: Creation
◼ Here’s the node class with constructors:
class intBSTnode {
private int
data;
private
intBSTnode
left,
right;
// Constructors
intBSTnode() {
left = null;
right=null;
}
intBSTnode(int
newData) {
this(newData,
null, null);
}
intBSTnode(int newData, intBSTnode lt, intBSTnode rt)
{ data = newData;
Binary Search Tree: Creation
Creating a Binary Search Tree
We need to make a class for the actual tree
The name of this class will be intBST
“Integer Binary Search Tree”
This class will have one intBSTnode variable
It will be called “root”
Why?
Because it will be a reference to the root of the tree!
From a main method, we can then make a new integer
Binary Search Tree (a new intBST)
Finally, within this intBST class, we will have many
methods to insert nodes, delete nodes, traverse the tree,
count the nodes, sum the nodes, etc.
Binary Search Tree: Creation
◼ Creating a Binary Search tree
◼ Here is the intBST class:
class intBST {
}
Binary Search Tree: Insertion
Insertion (of nodes) into a Binary Search Tree
Now that we have nodes, it is time to insert!
BSTs must maintain their ordering property
Smaller items to the left of any given root
And greater items to the right of that root
So when we insert, we MUST follow these rules
You simply start at the root and either
1) Go right if the new value is greater than the root
2) Go left if the new value is less than the root
Keep doing this till you come to an empty
position
An example will make this clear…
Binary Search Tree: Insertion
◼ Insertion into a Binary Search Tree
◼ Let’s assume we insert the following data values, in
their order of appearance into an initially empty BST:
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:
Create a new node with value 14 10
This node belongs in the right subtree
of node 10
14
Since 14 > 10
child of node 10
Binary Search Tree: Insertion
◼ Insertion into a Binary Search Tree
◼ 10, 14, 6, 2, 5, 15, and 17
Step 3:
Create a new node with value 6 10
This node belongs in the left subtree
of node 10
6 14
Since 6 < 10
of node 10
Binary Search Tree: Insertion
◼ Insertion into a Binary Search Tree
◼ 10, 14, 6, 2, 5, 15, and 17
Step 4:
Create a new node with value 2 10
This node belongs in the left subtree of node 10
◼ Since 2 < 10 6 14
The root of the left subtree is 6
The new node belongs in the left 2
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:
Create a new node with value 5 10
This node belongs in the left subtree
of node 10
6 14
◼ Since 5 < 10
The new node belongs in the left
subtree of node 6 2
Since 5 < 6
Step 6:
Create a new node with value 15 10
This node belongs in the right subtree
of node 10
6 14
◼ Since 15 > 10
The new node belongs in the right
subtree of node 14 2 15
◼ Since 15 > 14
The right subtree of node 14 is 5
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:
Create a new node with value 17 10
This node belongs in the right subtree
of node 10
6 14
◼ Since 17 > 10
The new node belongs in the right
subtree of node 14 2 15
Since 17 > 14
myBST.insert(20)
;
myBST.insert(18)
;
myBST.insert(33)
;
}
Deletion
Binary Trees: Deletion
Deletion From a Binary Search Tree
There are 3 possible cases:
10 10
6 14 6 14
4 8 12 18 4 8 18
2 16 2 16
10 10
6 14 6 14
4 8 12 18 2 8 12 18
2 16 16
10 10
6 18
6 14
4 8 16
4 8 18
15 17
2 16 2
Initial BST with node 14 17 BST after deletion of node 14. Node 18
15
marked for deletion has taken the place of the deleted node
and the entire subtree moved up one level.
Binary Trees: Deletion
Case 3: Deleting a Node with two children
Consider this example tree
We want to delete node 18
since node 18 can’t use its left pointer to point to more than one child
can’t point to both node 13 and node 32
What node could I replace the 18 with and still maintain the
binary search tree property? 59
18 67
13 32 63 72
10 15 25 43
59
18 67
Binary Trees: Deletion 13 32 63 72
10 15 25 43
18 67
Binary Trees: Deletion
13 32 63 72
10 15 25 43
◼ Deleting a Node with two children
◼ Thus, if we delete 18
◼ There are two possible nodes that could go into 18’s
position:
1) Node 15 (greatest value in left subtree)
2) Node 25 (smallest value in right subtree)
We simply pick one of these to put at 18’s position
18 67
Binary Trees: Deletion
13 32 63 72
10 15 25 43
Deleting a Node with two children
We are guaranteed that this node
Node 15 in this example
Has AT MOST only one child
Meaning it will be easy to delete!
Why is that? How is this
guarantee true?
The greatest node in a left subtree cannot have two
children
If it did, its right child would be greater than it
Similarly, the smallest node in a right subtree cannot
have two children
If it did, its left child would be smaller than it
Binary Trees: Deletion
◼ Deleting a Node with two children (Example)
59
59
18 67 18 67
13 32 63 72 13 32 63 72
10 15 25 43 10 15 25 43
Initial BST with node 18 marked for This node contains the logical predecessor
deletion. Note that this node has of the node to be deleted. Note that it is the
two children with values 13 and 32. greatest node in the left subtree of the
node to be deleted.
Binary Trees: Deletion
◼ Deleting a Node with two children (Example)
59
59
18 67 18 67
13 32 63 72 13 32 63 72
10 15 25 43 10 15 25 43
Initial BST with node 18 marked for This node contains the logical successor of
deletion. Note that this node has the node to be deleted. Note that it is the
two children with values 13 and 32. smallest node in the right subtree of the
node to be deleted.
Binary Trees: Deletion
◼ Deleting a Node with two children (Example)
59
59
18 67 15 67
13 32 63 72 13 32 63 72
10 15 25 43 10 25 43
This node contains the logical predecessor The BST after the deletion of node
of the node to be deleted. Note that it is the 18 using the replacement by the
greatest node in the left subtree of the logical predecessor node.
node to be deleted.
Binary Trees: Deletion
◼ Deleting a Node with two children (Example)
59
59
18 67 25 67
13 32 63 72 13 32 63 72
10 15 25 43 10 15 43
This node contains the logical successor of The BST after the deletion of node
the node to be deleted. Note that it is the 18 using the replacement by the
smallest node in the right subtree of the logical successor node.
node to be 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
Node deleteRec(Node root, int key)
{
if (root == null) /* Base Case: If the tree is empty */
return root;
if (key < root.key) /* Otherwise, recur down the tree */
root.left = deleteRec(root.left, key);
else if (key > root.key)
root.right = deleteRec(root.right, key);
// node with two children: Get the smallest in the right subtree
root.key = minValue(root.right);
return root;
}
int minValue(Node root)
{
int minv = root.key;
while (root.left != null) {
minv = root.left.key;
root = root.left;
}
return minv;
}
Practice Problems
Binary Trees: Practice
Problems
Write a method that Sum the values of nodes in a Tree
int sumNodes()
{ return(sumNodes(root
));
}
int sumNodes(intBSTnode p) {
if (p == null)
return(0);
else {
return
p.data +
sumNodes(p
.left) +
sumNodes(p
.right);
}
}
Binary Trees: Practice
Problems
Write a method that counts the number of nodes
in a binary tree
int countNodes()
{ return(countNodes(root
));
}
int countNodes(intBSTnode p) {
if (p == null)
return(0);
else {
return
1 +
countNodes
(p.left) +
countNodes
(p.right);
}
Binary Trees: Practice
Problems
◼ Print Even Nodes
void printEven(intBSTnode p) {
if (p != null) {
if (p.data % 2 == 0)
System.out.println( p.data);
printEven(p.left);
printEven(p-.ight);
}
}
return rightHeight + 1;
}
Binary Trees: Practice
Problems
Write a recursive method that returns the largest element in a BST
So where is the largest node located
Either the root or the greatest node in the right subtree
int numLeaves ()
{ return(numLeaves(root
));
}
int numLeaves(intBSTnode p) {
if (p != NULL) {
if (p.left == NULL && p.right == NULL)
return 1;
else
return numLeaves(p.left) +
numLeaves(p.right);
}
else
return 0;
}
Binary Trees: Practice
Problems
Write a recursive method that counts the number of
nodes with a single child
int one(intBSTnode p) {
if (p != NULL) {
if (p.left == null)
if (p.right != null)
return 1 + one(p.right);
else if (p.right == null)
if (p.left !=
null)
return 1 +
one(p.left);
else
}
return one(p.left)
+ one(p.right);
}
return 0;