Binary Trees
Binary Trees
parent, ancestor,
descendant, path,
depth, height, level,
leaf node, internal
node, subtree.
Binary Tree Example
Notation: Node,
children, edge,
parent, ancestor,
descendant, path,
depth, height, level,
leaf node, internal
node, subtree.
Binary Tree Example
Notation: Node,
children, edge, Left Child
parent, ancestor, of A
Right Child
descendant, path, of A
descendant, path,
depth, height, level, 1 1 1
3+1=4 3 3 3
Depth of a node…
3
Level of a node…
Height of a tree
Binary Tree Example
Notation: Node,
children, edge, parent,
ancestor, descendant,
path, depth, height,
level, leaf node,
internal node, subtree.
Internal node: At least one non-empty children
Left subtree of A
Are the following two trees same?
Full and Complete Binary Trees
Full binary tree: Each node is either a leaf or
internal node with exactly two non-empty children.
Complete binary tree: If the height of the tree is d,
then all leaves except possibly level d-1 are
completely full. The bottom level has all nodes to
the left side.
Full Complete
Full Binary Tree Theorem (1)
Theorem: The number of leaves in a non-empty
full binary tree is one more than the number of
internal nodes.
Proof (by Mathematical Induction):
Base case: A full binary tree with 1 internal node must
have two leaf nodes.
Induction Hypothesis: Assume any full binary tree T
containing n-1 internal nodes has n leaves.
Full Binary Tree Theorem (2)
Induction Step:
We want to prove the following here:
Any traversal that lists every node in the tree exactly once
is called an enumeration of the tree’s nodes.
23
Preorder Traversal
• In a preorder traversal, a node is
visited before its descendants
Algorithm preOrder(v)
• If a tree is ordered, then the
subtrees are traversed according visit(v)
to the order of the children for each child w of v
• We assume a left to right order preOrder (w)
1 A
2 9
B
5 C D
3 4 6 7 8
E F I G H
Preorder: ABEFCIGHD
Note: this is not a binary tree
Postorder Traversal
• In a postorder traversal, a Algorithm postOrder(v)
node is visited after its
for each child w of v
descendants
postOrder (w)
visit(v)
A 9
8
3
B 7 C D
1 2 6
4 5
E F I G H
Postorder: EFBIGHCDA
Note: this is not a binary tree
Inorder Traversal
• In an inorder traversal a node Algorithm inOrder(v)
is visited after its left subtree if isInternal (v)
inOrder (leftChild (v))
and before its right subtree:
– Traverse the left subtree in inorder.
visit(v)
– Visit the root. if isInternal (v)
– Traverse the right subtree in inorder. inOrder (rightChild (v))
3 4
8
6 1 9
6
2 8 2 7
5
1 4 7 9
Inorder: DGBAHEICF
3 5
Note: Only applicable to a binary tree 26
Level Order Traversal
• In a level order traversal, every node on a level is
visited before going to a lower level
1 A
2 4
B
3 C D
5 6 7 8 9
E F I G H
27
Pre-Order Traversal
1. A
2. B
3. D
4. C
5. E
6. G
7. F
8. H
9. I
Pre-Order Traversal
1. A
2. B
3. D
4. C
5. E
6. G
7. F
8. H
9. I
Pre-Order Traversal
1. A
2. B
3. D
4. C
5. E
6. G
7. F
8. H
9. I
Pre-Order Traversal
1. A
2. B
3. D
4. C
5. E
6. G
7. F
8. H
9. I
Pre-Order Traversal
1. A
2. B
3. D
4. C
5. E
6. G
7. F
8. H
9. I
Pre-Order Traversal
1. A
2. B
3. D
4. C
5. E
6. G
7. F
8. H
9. I
Pre-Order Traversal
1. A
2. B
3. D
4. C
5. E
6. G
7. F
8. H
9. I
Pre-Order Traversal
1. A
2. B
3. D
4. C
5. E
6. G
7. F
8. H
9. I
Pre-Order Traversal
1. A
2. B
3. D
4. C
5. E
6. G
7. F
8. H
9. I
Pre-Order Traversal
1. A
2. B
3. D
4. C
5. E
6. G
7. F
8. H
9. I
Post-Order Traversal
1. D
2. B
3. G
4. E
5. H
6. I
7. F
8. C
9. A
Post-Order Traversal
1. D
2. B
3. G
4. E
5. H
6. I
7. F
8. C
9. A
Post-Order Traversal
1. D
2. B
3. G
4. E
5. H
6. I
7. F
8. C
9. A
Post-Order Traversal
1. D
2. B
3. G
4. E
5. H
6. I
7. F
8. C
9. A
Post-Order Traversal
1. D
2. B
3. G
4. E
5. H
6. I
7. F
8. C
9. A
Post-Order Traversal
1. D
2. B
3. G
4. E
5. H
6. I
7. F
8. C
9. A
Post-Order Traversal
1. D
2. B
3. G
4. E
5. H
6. I
7. F
8. C
9. A
Post-Order Traversal
1. D
2. B
3. G
4. E
5. H
6. I
7. F
8. C
9. A
Post-Order Traversal
1. D
2. B
3. G
4. E
5. H
6. I
7. F
8. C
9. A
Post-Order Traversal
1. D
2. B
3. G
4. E
5. H
6. I
7. F
8. C
9. A
In-Order Traversal
1. B
2. D
3. A
4. G
5. E
6. C
7. H
8. F
9. I
In-Order Traversal
1. B
2. D
3. A
4. G
5. E
6. C
7. H
8. F
9. I
In-Order Traversal
1. B
2. D
3. A
4. G
5. E
6. C
7. H
8. F
9. I
In-Order Traversal
1. B
2. D
3. A
4. G
5. E
6. C
7. H
8. F
9. I
In-Order Traversal
1. B
2. D
3. A
4. G
5. E
6. C
7. H
8. F
9. I
In-Order Traversal
1. B
2. D
3. A
4. G
5. E
6. C
7. H
8. F
9. I
In-Order Traversal
1. B
2. D
3. A
4. G
5. E
6. C
7. H
8. F
9. I
In-Order Traversal
1. B
2. D
3. A
4. G
5. E
6. C
7. H
8. F
9. I
In-Order Traversal
1. B
2. D
3. A
4. G
5. E
6. C
7. H
8. F
9. I
In-Order Traversal
1. B
2. D
3. A
4. G
5. E
6. C
7. H
8. F
9. I
Pre-Order Traversal Code V1
/** @param rt The root of the subtree */
void preorder(BinNode rt)
{
if (rt == null) return; // Empty subtree
visit(rt);
preorder([Link]());
preorder([Link]());
}
Pre-Order Traversal Code V2
/** @param rt The root of the subtree */
void preorder2(BinNode rt) // Not so good
{
visit(rt);
if ([Link]() != null) preorder([Link]());
if ([Link]() != null) preorder([Link]());
}
Preorder vs preorder2
• preorder2 makes only half as many recursive
calls. (Why?)
• On the other hand, preorder2 must access the
left and right child pointers twice as often.
• The net result is little or no performance
improvement.
void preorder(BinNode rt)
{
if (rt == null) return; // Empty subtree
visit(rt);
preorder([Link]());
preorder([Link]());
}
C++[Link]
Binary Tree Implementation
Binary Tree Implementation
Some important issues
• whether the same class definition will be used for
leaves and internal nodes.
– Using the same class for both will simplify the
implementation,
– but might be an inefficient use of space.
– Some applications require data values only for the leaves.
– Other applications require one type of value for the leaves
and another for the internal nodes.
– Also, it seems wasteful to store child pointers in the leaf
nodes.
Binary Tree Implementation
4x (2x + a) + c
4 * x * (2 * x + a) + c
Binary Tree Implementation
• Internal nodes store operators
– could store a small code identifying
the operator (a single byte for the
operator’s symbol)
• the leaves store operands
– i.e., variable names or numbers,
4x (2x + a) + c (considerably larger in order to
4 * x * (2 * x + a) + c handle the wider range of possible
values)
– No child pointers though
Different nodes implementation with
inheritance (1)
C++[Link]
Different nodes implementation with
inheritance (2)
C++[Link]
Why two Implementations?
[Design Patterns]
• Design patterns capture reusable pieces
of design wisdom.
• Goals:
– Quickly communicate design wisdom to new
designers
– Give a shared vocabulary to designers
• WE WILL NOT FOCUS ON THIS
Space Requirements
• Every node has two pointers to its children
• total space = n(2P + D) for a tree of n nodes
– P: space required by a pointer
– D: amount of space required by a data value
• So, total overhead: 2Pn
• Overhead fraction: 2P/(2P+D)
• P = D => 2/3rd of its total space is overhead
• From the Full Binary Tree Theorem: Half of the
pointers are null.
– half of the pointers are “wasted” NULL values that serve only to
indicate tree structure, but which do not provide access to new
data.
Space Overhead
• A common implementation is not to store any
actual data in a node
– but rather a pointer to the data record.
• In this case, each node will typically store
three pointers all of which are overhead:
– overhead fraction of 3P/(3P + D)
– P = D => 3/4th of its total space is overhead
Space Overhead
• If only leaves store data values, then the fraction of
total space devoted to overhead depends on
whether the tree is full.
– If the tree is not full, then conceivably there might only
be one leaf node at the end of a series of internal nodes.
– Thus, the overhead can be an arbitrarily high percentage
• The overhead fraction drops as the tree becomes
closer to full, being lowest when the tree is truly full.
– In this case, about one half of the nodes are internal.
Space Overhead
Eliminate pointers from the leaf nodes:
(Assuming P=D).
Note that some method is
needed to distinguish leaves
from internal nodes. So some
space is needed here which
we ignore in our analysis
Space Overhead
• a better implementation would have the
internal nodes store two pointers and no data
field while the leaf nodes store only a pointer
to the data field.
– (3P)/(3P + D) => ¾ when D = P. Full Binary Tree
n/2 IN has 2P
~n/2 L has 1P
~n/2 L has 1D
Array Implementation
Complete Binary Tree
Position 0 1 2 3 4 5 6 7 8 9 10 11
Parent -- 0 0 1 1 2 2 3 3 4 4 5
Left Child 1 3 5 7 9 11 -- -- -- -- -- --
Right Child 2 4 6 8 10 -- -- -- -- -- -- --
Left Sibling -- -- 1 -- 3 -- 5 -- 7 -- 9 --
Right Sibling -- 2 -- 4 -- 6 -- 8 -- 10 -- --
Array Implementation
Position 0 1 2 3 4 5 6 7 8 9 10 11
Parent -- 0 0 1 1 2 2 3 3 4 4 5
Left Child 1 3 5 7 9 11 -- -- -- -- -- --
Right Child 2 4 6 8 10 -- -- -- -- -- -- --
Left Sibling -- -- 1 -- 3 -- 5 -- 7 -- 9 --
Right Sibling -- 2 -- 4 -- 6 -- 8 -- 10 -- --
Array Implementation
Position 0 1 2 3 4 5 6 7 8 9 10 11
Parent -- 0 0 1 1 2 2 3 3 4 4 5
Left Child 1 3 5 7 9 11 -- -- -- -- -- --
Right Child 2 4 6 8 10 -- -- -- -- -- -- --
Left Sibling -- -- 1 -- 3 -- 5 -- 7 -- 9 --
Right Sibling -- 2 -- 4 -- 6 -- 8 -- 10 -- --
Array Implementation
Position 0 1 2 3 4 5 6 7 8 9 10 11
Parent -- 0 0 1 1 2 2 3 3 4 4 5
Left Child 1 3 5 7 9 11 -- -- -- -- -- --
Right Child 2 4 6 8 10 -- -- -- -- -- -- --
Left Sibling -- -- 1 -- 3 -- 5 -- 7 -- 9 --
Right Sibling -- 2 -- 4 -- 6 -- 8 -- 10 -- --
Array Implementation
Position 0 1 2 3 4 5 6 7 8 9 10 11
Parent -- 0 0 1 1 2 2 3 3 4 4 5
Left Child 1 3 5 7 9 11 -- -- -- -- -- --
Right Child 2 4 6 8 10 -- -- -- -- -- -- --
Left Sibling -- -- 1 -- 3 -- 5 -- 7 -- 9 --
Right Sibling -- 2 -- 4 -- 6 -- 8 -- 10 -- --
Array Implementation
Position 0 1 2 3 4 5 6 7 8 9 10 11
Parent -- 0 0 1 1 2 2 3 3 4 4 5
Left Child 1 3 5 7 9 11 -- -- -- -- -- --
Right Child 2 4 6 8 10 -- -- -- -- -- -- --
Left Sibling -- -- 1 -- 3 -- 5 -- 7 -- 9 --
Right Sibling -- 2 -- 4 -- 6 -- 8 -- 10 -- --