Data StructureChapter 5
Dr. Patrick Chan
School of Computer Science and Engineering
South China University of Technology
Binary Trees
http://125.216.243.100/csDS/
2
Lec 5: Binary Tree
Outline
� Recursion (Ch 2.4)
� Binary Trees (Ch 5)
� Introduction (Ch 5.1)
� Traversal (Ch 5.2)
� Implementation (Ch 5.3)
� Binary Search Trees (Ch 5.4)
� Priority Queues and Heaps (Ch 5.5)
� Huffman Coding Trees (Ch 5.6)
3
Lec 5: Binary Tree
Recursion
� A recursion is a procedure which calls itself
� The recursive procedure call must use different
arguments from the original one
� Otherwise the procedure would always get into
an infinite loop
4
Lec 5: Binary Tree
Recursion
� Example:
� Factorial function
� n! = n · (n-1) · … · 2 · 1
−⋅
==
elsenfn
nnf
)1(
0 if1)(
int factorial(int n) {
if (n == 0)
return 1;
else
return n * factorial(n-1);
}
factorial(3)
factorial(2)
factorial(1)
factorial(0)
3 * factorial(2)
2 * factorial(1)
1 * factorial(0)
factorial(2)=2
factorial(1)=1
factorial(0)=1
factorial(4)4 * factorial(3)
factorial(3)=6
ans = 24
5
Lec 5: Binary Tree
Recursion
� Recursive Call� Calls to the current method
� Each recursive call should be defined so that it makes progress towards a base case
� Base Case� Values of the input variables for which we perform no recursive
calls are called base cases
� At least one base case
� Every possible chain of recursive calls must eventually reach a base case
int factorial(int n) {
if (n == 0)
return 1;
else
return n * factorial(n-1);
}
factorial(3)
factorial(2)
factorial(1)
factorial(0)
factorial(4)
6
Lec 5: Binary Tree
Recursion
� Example has two Recursive Calls
>
>
=
−⋅=
even is 0 if
odd is 0 if
0 if
)2/,(
)2/)1(,(
1
),(2
2
x
x
x
nxp
nxpxnxp
24 = 2(4/2)*2 = (24/2)2 = (22)2 = 42 = 16
25 = 21+(4/2)*2 = 2(24/2)2 = 2(22)2 = 2(42) = 32
26 = 2(6/ 2)*2 = (26/2)2 = (23)2 = 82 = 64
27 = 21+(6/2)*2 = 2(26/2)2 = 2(23)2 = 2(82) = 128
int power(int x, int n) {if (n == 0)
return 1;if (n % 2 == 1) {
y = Power(x, (n - 1)/2);return x * y * y;
}else {
y = Power(x, n/2);return y · y;
}}
It is important that we used a
variable twice here rather
than calling the method twice
Base Case
Recursive Call
7
Lec 5: Binary Tree
A B C
Recursion
� Tower of Hanoi
8
Lec 5: Binary Tree
Recursion: Tower of HanoiMore than 1 steps
More than 1 steps
1 step
More than 1 steps
Break Down
Recursive Call Recursive Call
9
Lec 5: Binary Tree
Recursion: Tower of HanoiMore than 1 steps
More than 1 steps
1 step
More than 1 steps
Break Down
Recursive Call Recursive Call
10
Lec 5: Binary Tree
Recursion: Tower of HanoiMore than 1 steps
1 step
1 step
1 step
Break Down
Base Case Base Case
11
Lec 5: Binary Tree
Recursion: Tower of Hanoi
The solution
12
Lec 5: Binary Tree
Recursion: Tower of Hanoi
� Solution:
void solveTowers(int count, char source, char destination, char spare) {
if (count == 1) {cout << "Move top disk from pole " << source <<
" to pole " << destination);} else {solveTowers(count-1, source, spare, destination); // LeftsolveTowers(1, source, destination, spare); // 1 stepsolveTowers(count-1, spare, destination, source); // Right
} // end if} // end solveTowers
13
Lec 5: Binary Tree
Recursion: Observation
: Same Algorithm
Break down the problem into smaller parts
and eventually reach a base case
14
Lec 5: Binary Tree
Binary Tree: Introduction
� A binary tree is made up of a finite set of nodes
that is either empty or consists of a node called
the root together with two binary trees which are
disjoint from each other and from the root
A
B D
C E H
F G I
J
15
Lec 5: Binary Tree
R
BP
CVH
FG
J
Depth: 0
Level: 0
Depth: 1
Level: 1
Depth: 2
Level: 2
Depth: 3
Level: 3
Depth: 4
Level: 4
Binary Tree: Introduction
Height is 5
Root
Parent of V
Ancestors of V
Sibling of V
Children of V
Descendants of V
Internal Node
Leaf Node
Edge
Subtree rooted at V
16
Lec 5: Binary Tree
Binary Tree
� Full binary tree
� Each node being either
� Leaf
� Internal node with exactly
two non-empty children
A
B D
E H
F G
A
B D
E H
F
A
B D
����
��������
17
Lec 5: Binary Tree
Binary Tree
� Complete binary tree
� If the height of the tree is d,
then all levels except possibly level d-1 are
completely full
� The bottom level has all
nodes filled in from the left
side
A
BD
CEH
GIJ
T
A
D
EH
A
BD
CT
���� ����
����
18
Lec 5: Binary Tree
Binary Tree
Full Binary Tree Theorem
� Theorem 1
The number of leaves in a non-empty full
binary tree is one more than the number of
internal nodes
A
BD
CEH T
Leaves 5Internal Nodes 4
A
B D
E H
F G
H I
Leaves 4Internal Nodes 3
19
Lec 5: Binary Tree
Binary Tree
Full Binary Tree Theorem
� Theorem 2
The number of null pointers in a non-empty
binary tree is one more than the number of
nodes in the tree
A
BD
CEH T
Leaves 5Internal Nodes 4Null Pointers 5 x 2 = 10
5 + 4 = 9Nodes
A
B D
E H
F G
H I
Leaves 4Internal Nodes 3Null Pointers 4 x 2 = 8
4 + 3 = 7Nodes
20
Lec 5: Binary Tree
Binary Tree: Node ADT
Template <class Elem> class BinNode {
public:
virtual Elem& val( ) =0;
virtual BinNode* left( ) const = 0;
virtual BinNode* right( ) const = 0;
virtual void setVal( const Elem& ) = 0;
virtual void setLeft( BinNode* ) = 0;
virtual void setRight( BinNode* ) = 0;
virtual bool isLeaf( ) = 0;
}
A
B D
C E H
F G I
J
21
Lec 5: Binary Tree
Binary Tree: Node// Binary tree node classtemplate <class Elem>class BinNodePtr : public BinNode<Elem> {
private:Elem it; // The node's valueBinNodePtr* lc; // Pointer to left childBinNodePtr* rc; // Pointer to right child
public:BinNodePtr() { lc = rc = NULL; }BinNodePtr(Elem e, BinNodePtr* l=NULL, BinNodePtr* r=NULL)
{ it = e; lc = l; rc = r; }Elem& val() { return it; }void setVal(const Elem& e) { it = e; }inline BinNode<Elem>* left() const
{ return lc; }void setLeft(BinNode<Elem>* b)
{ lc = (BinNodePtr*)b; }inline BinNode<Elem>* right() const
{ return rc; }void setRight(BinNode<Elem>* b)
{ rc = (BinNodePtr*)b; }bool isLeaf()
{ return (lc == NULL) && (rc == NULL); }};
73
NULL NULL
BinNodePtr aNode(73);
22
Lec 5: Binary Tree
Binary Tree: Traversals
� Traversal is a process for
visiting the nodes in some
order
� Any traversal that lists
every node in the tree
exactly once is called an
enumeration of the tree’s
nodes
A
B D
C E H
F G I
J
23
Lec 5: Binary Tree
� Preorder traversal
� Visit each node before visiting its children
�
� Postorder traversal
� Visit each node after visiting its children
�
� Inorder traversal
� Visit the left subtree, then the node, then the right subtree
�
Binary Tree: Traversals
A
B D
C E H
F G I
J
A B C D E F G H JI
C B F G E J I H AD
C B A F E G D I HJ
24
Lec 5: Binary Tree
Binary Tree: Traversals
template <class Elem>
void preorder(BinNode<Elem>* subroot) {
if (subroot == NULL) return; // Empty
visit(subroot); // Perform some actions
preorder(subroot->left()); // left
preorder(subroot->right()); // right
}
template <class Elem>
void postorder(BinNode<Elem>* subroot) {
if (subroot == NULL) return; // Empty
postorder(subroot->left()); // left
postorder(subroot->right()); // right
visit(subroot); // Perform some actions
}
template <class Elem>
void inorder(BinNode<Elem>* subroot) {
if (subroot == NULL) return; // Empty
inorder(subroot->left()); // left
visit(subroot); // Perform some actions
inorder(subroot->right()); // right
}
� Preorder traversal
� Visit each node before visiting its children
� Postorder traversal
� Visit each node after visiting its children
� Inorder traversal� Visit the left subtree,
then the node, then the right subtree
25
Lec 5: Binary Tree
Binary Tree: Traversals
Which one is better?
template <class Elem>
void preorder1(BinNode<Elem>* subroot) {
if (subroot == NULL) return; // Empty
visit(subroot); // Perform some action
preorder1(subroot->lc());
preorder1(subroot->rc());
}
template <class Elem>
void preorder2(BinNode<Elem>* subroot) {
visit(subroot); // Perform some action
if (subroot->left() != NULL)
preorder2(subroot->lc());
if (subroot->right() != NULL)
preorder2(subroot->rc());
}
(1)
(2)
check if the tree is empty at first
check if the right and left point are empty
A
B D
C E H
F G I
J
26
Lec 5: Binary Tree
Binary Tree: Traversals
Which one is better?
� Advantage of Case 2
� Reduce half recursive calls(refer to Theorem 2 in slide 19)
� Advantage of Case 1
� Only one base case checking
� For complex traversals, checking criteria may be very complicated
� Avoid the bugs
� E.g. the initial call passes an empty tree
� Case 1 should be used
A
B D
C E H
F G I
J
27
Lec 5: Binary Tree
Binary Tree
Different Leafs & Internal Nodes
� Each node stores the
same kind of data
� Internal nodes and
leaves store different
types of dataA
B C
D F
G H
NULL NULL
NULL NULL
NULL NULL NULL NULL
-
*
* +
2
a*
x
4 x
c
4x(2x+a) - c
28
Lec 5: Binary Tree
Binary Tree
Different Leafs & Internal Nodes
� Three implementation methods
� Union
� Inheritance
� Inheritance with virtual function
29
Lec 5: Binary Tree
Binary Tree: Different Leafs & Internal Nodes
Union Implementationenum Nodetype {leaf, internal};
class VarBinNode { // Generic node classpublic:
Nodetype mytype; // Store type for nodeunion {
struct { // Internal nodeVarBinNode* left; // Left childVarBinNode* right; // Right childOperator opx; // Value
} intl;Operand var; // Leaf: Value only
};// Leaf constructorVarBinNode(const Operand& val)
{ mytype = leaf; var = val; }// Internal node constructorVarBinNode(const Operator& op, VarBinNode* l, VarBinNode* r) {
mytype = internal; intl.opx = op;intl.left = l; intl.right = r;
}bool isLeaf() { return mytype == leaf; }VarBinNode* leftchild()
{ return intl.left; }VarBinNode* rightchild()
{ return intl.right; }};
Indicate if it is an
internal node or a leafTwo types of information
Two different constructor
30
Lec 5: Binary Tree
Binary Tree: Different Leafs & Internal Nodes
Union Implementation
� Disadvantage
� A node is total sizes for leaf and internal node
// Preorder traversal
void traverse(VarBinNode* subroot) {
if (subroot == NULL) return;
if (subroot->isLeaf())
cout << "Leaf: “
<< subroot->var << "endl";
else {
cout << "Internal: “
<< subroot->intl.opx << "endl";
traverse(subroot->leftchild());
traverse(subroot->rightchild());
}
}
31
Lec 5: Binary Tree
Binary Tree: Different Leafs & Internal Nodes
Inheritance Implementation class VarBinNode { // Abstract base classpublic:
virtual bool isLeaf() = 0;};
class LeafNode : public VarBinNode { // Leafprivate:
Operand var; // Operand valuepublic:
LeafNode(const Operand& val){ var = val; } // Constructor
bool isLeaf() { return true; }Operand value() { return var; }
};
class IntlNode : public VarBinNode { // Internal nodeprivate:
VarBinNode* left; // Left childVarBinNode* right; // Right childOperator opx; // Operator value
public:IntlNode(const Operator& op, VarBinNode* l, VarBinNode* r)
{ opx = op; left = l; right = r; }bool isLeaf() { return false; }VarBinNode* leftchild() { return left; }VarBinNode* rightchild() { return right; } Operator value() { return opx; }
};
32
Lec 5: Binary Tree
Binary Tree: Different Leafs & Internal Nodes
Inheritance Implementationvoid traverse(VarBinNode *subroot) { // Preorder traversal
if (subroot == NULL) return; // Empty
if (subroot->isLeaf()) // Do leaf node
cout << "Leaf: "
<< ((LeafNode *)subroot)->value()
<< endl;
else { // Do internal node
cout << "Internal: "
<< ((IntlNode *)subroot)->value()
<< endl;
traverse(((IntlNode *)subroot)->leftchild());
traverse(((IntlNode *)subroot)->rightchild());
}
}
� Disadvantage
� The traverse is still complicated (if-then-else is used)
33
Lec 5: Binary Tree
Binary Tree: Different Leafs & Internal Nodes
Inheritance with virtual functionclass VarBinNode { // Abstract base class
public:
virtual bool isLeaf() = 0;
virtual void trav() = 0;
};
class LeafNode : public VarBinNode { // Leaf
private:
Operand var; // Operand value
public:
LeafNode(const Operand& val) { var = val; } // Constructor
bool isLeaf() { return true; }
Operand value() { return var; }
void trav() { cout << "Leaf: " << value() << endl; }
};
34
Lec 5: Binary Tree
Binary Tree: Different Leafs & Internal Nodes
Inheritance with virtual functionclass IntlNode : public VarBinNode {
private:
VarBinNode* lc; // Left child
VarBinNode* rc; // Right child
Operator opx; // Operator value
public:
IntlNode(const Operator& op, VarBinNode* l, VarBinNode* r)
{ opx = op; lc = l; rc = r; }
bool isLeaf() { return false; }
VarBinNode* left() { return lc; }
VarBinNode* right() { return rc; }
Operator value() { return opx; }
void trav() {
cout << "Internal: " << value() << endl;
if (left() != NULL) left()->trav();
if (right() != NULL) right()->trav();
}
};
35
Lec 5: Binary Tree
Binary Tree: Different Leafs & Internal Nodes
Inheritance with virtual function
// Preorder traversal
void traverse(VarBinNode *root) {
if (root != NULL)
root->trav();
}
� Comparisons
� Inheritance Implementation
� Easily to add new methods to the tree class that traverse the
tree
� Inheritance with virtual function
� More preferred if the internal behavior of the nodes should
be hided
36
Lec 5: Binary Tree
Binary Tree
Space Requirements
� Overhead Space
Amount of space necessary to maintain the
data structure
� i.e any space not used to store the data records
� Overhead Fraction
Amount of overhead space divided by amount
of total space used
37
Lec 5: Binary Tree
Binary Tree
Space Requirements
� Example
� Full tree with all nodes are the same
(two pointers to children and one element):
� Total space required: n(2p + d)
� n: number of nodes
� p: the amount of space required by a pointer
� d: the amount of space required by a data value
� Overhead Space: 2pn
� Overhead Fraction: 2p / (2p + d)
� If p = d, it means 2/3 of total space is taken up in overhead
38
Lec 5: Binary Tree
☺☺☺☺ Small Quiz!!!! ☺☺☺☺
Q1. Write a recursive function that returns the
height of a binary tree
template <class Elem>
int findHeight(BinNode<Elem>* subroot){...}
if (subroot == NULL) return 0; // Empty subtree
return 1 + max(height(subroot->left()),
height(subroot->right()));
}
A
B D
C E H
F G
39
Lec 5: Binary Tree
☺☺☺☺ Small Quiz!!!! ☺☺☺☺
Q2. Write a recursive function that search value
K in a binary tree. The function returns true
if value K is existtemplate <class Key, class Elem, class KEComp>
bool search(BinNode<Elem>* subroot, Key K){...}
if (subroot == NULL) return false;
if (subroot->value() == K) return true;
elseif (search(subroot->left())) return true;
else return search(subroot->right());
}A
B D
C E H
F G
40
Lec 5: Binary Tree
Binary Search Trees
� Binary Search Tree (BST) is
a special case of Binary
Tree
� All elements stored in the
left subtree of a node with value K have values < K
� All elements stored in the
right subtree of a node with value K have values >= K
37
24
327
2
42
42
120
40
120
42
427
2 32
37
40
23
41
Lec 5: Binary Tree
Binary Search Trees: ADT// BST implementation for the Dictionary ADT
template <class Key, class Elem, class KEComp, class EEComp>
class BST : public Dictionary<Key, Elem,KEComp, EEComp> {
private:
BinNode<Elem>* root; // Root of the BST
int nodecount; // Number of nodes
void clearhelp(BinNode<Elem>*);
BinNode<Elem>* inserthelp(BinNode<Elem>*, const Elem&);
BinNode<Elem>* deletemin(BinNode<Elem>*,BinNode<Elem>*&);;;;BinNode<Elem>* removehelp
(BinNode<Elem>*,const Key&,BinNode<Elem>*&);
bool findhelp(BinNode<Elem>*, const Key&,Elem&) const;
void printhelp(BinNode<Elem>*, int) const;
public:
BST() { root = NULL; nodecount = 0; }
~BST() { clearhelp(root); }
void clear() { clearhelp(root); root = NULL; nodecount = 0;}}…
42
Lec 5: Binary Tree
Binary Search Trees: ADT
bool insert(const Elem& e) {
root = inserthelp(root, e);
nodecount++;
return true;
}
bool remove(const Key& K, Elem& e) {
BinNode<Elem>* t = NULL;
root = removehelp(root, K, t);
if (t == NULL) return false;
e = t->val();
nodecount--;
delete t;
return true;
}
…
43
Lec 5: Binary Tree
Binary Search Trees: ADTbool removeAny(Elem& e) { // Delete min value
if (root == NULL) return false; // Empty
BinNode<Elem>* t;
root = deletemin(root, t);
e = t->val();
delete t;
nodecount--;
return true;
}
bool find(const Key& K, Elem& e) const
{ return findhelp(root, K, e); }
int size() { return nodecount; }
void print() const {
if (root == NULL)
cout << "The BST is empty.\n";
else printhelp(root, 0);
}
}
44
Lec 5: Binary Tree
Binary Search Trees: ADT
inserthelp functiontemplate <class Key, class Elem, class KEComp, class EEComp>
BinNode<Elem>* BST<Key,Elem,KEComp,EEComp>::
inserthelp( BinNode<Elem>* subroot, const Elem& val ) {
if (subroot == NULL) // Empty: create node
return new BinNodePtr<Elem>(val,NULL,NULL);
if (EEComp::lt(val, subroot->val()))
subroot->setLeft(inserthelp(subroot->left(), val));
else
subroot->setRight(inserthelp(subroot->right(), val));
return subroot; // Return subtree with node inserted
}
Base Case
Recursive
Call 1
Recursive
Call 2
root=inserthelp(root,23); root
NULL
NULL NULL
23
root
23BCRC1RC2Return
subtree=
NULL
bool insert(const Elem& e) {
root = inserthelp(root, e);nodecount++;return true;
}
45
Lec 5: Binary Tree
BCRC1RC2Return
Binary Search Trees: ADT
inserthelp functiontemplate <class Key, class Elem, class KEComp, class EEComp>
BinNode<Elem>* BST<Key,Elem,KEComp,EEComp>::
inserthelp( BinNode<Elem>* subroot, const Elem& val ) {
if (subroot == NULL) // Empty: create node
return new BinNodePtr<Elem>(val,NULL,NULL);
if (EEComp::lt(val, subroot->val()))
subroot->setLeft(inserthelp(subroot->left(), val));
else
subroot->setRight(inserthelp(subroot->right(), val));
return subroot; // Return subtree with node inserted
}
Base Case
Recursive
Call 1
Recursive
Call 2
root
NULL NULL
23root=inserthelp(root,11);
NULL NULL
11
root=inserthelp(root,23);
root23.L
11root
BCRC1RC2Return
subtree=
23 subtree=
NULL
bool insert(const Elem& e) {
root = inserthelp(root, e);nodecount++;return true;
}
46
Lec 5: Binary Tree
BCRC1RC2Return
BCRC1RC2Return
BCRC1RC2Return
Binary Search Trees: ADT
inserthelp functiontemplate <class Key, class Elem, class KEComp, class EEComp>
BinNode<Elem>* BST<Key,Elem,KEComp,EEComp>::
inserthelp( BinNode<Elem>* subroot, const Elem& val ) {
if (subroot == NULL) // Empty: create node
return new BinNodePtr<Elem>(val,NULL,NULL);
if (EEComp::lt(val, subroot->val()))
subroot->setLeft(inserthelp(subroot->left(), val));
else
subroot->setRight(inserthelp(subroot->right(), val));
return subroot; // Return subtree with node inserted
}
Base Case
Recursive
Call 1
Recursive
Call 2
root
NULL
23root=inserthelp(root,11);
NULL NULL
11
root=inserthelp(root,23);
root23.L
11
root=inserthelp(root,19);
NULL NULL
19
11.R
19root
subtree=
NULL
subtree=
11
subtree=
23
bool insert(const Elem& e) {
root = inserthelp(root, e);nodecount++;return true;
}
47
Lec 5: Binary Tree
Binary Search Trees: ADT
deletemin functiontemplate <class Key, class Elem, class KEComp, class EEComp>
BinNode<Elem>* BST<Key, Elem, KEComp, EEComp>::
deletemin(BinNode<Elem>* subroot, BinNode<Elem>*& min) {
if (subroot->left() == NULL) {
min = subroot;
return subroot->right();
}
else { // Continue left
subroot->setLeft(
deletemin(subroot->left(), min));
return subroot;
}
}
root
NULL
23
NULL
11
NULL NULL
19
Base Case
Recursive Call
BCRC
root
11.R
(19)
BCRC
23.L
root
root=deletemin(root,aMin);
aMin
NULL
subtree=
23 subtree=
11
48
Lec 5: Binary Tree
template <class Key, class Elem, class KEComp, class EEComp>BinNode<Elem>* BST<Key,Elem,KEComp,EEComp>::
removehelp(BinNode<Elem>* subroot, const Key& K, BinNode<Elem>*& t) {
if (subroot == NULL) return NULL;
else if (KEComp::lt(K, subroot->val()))
subroot->setLeft(removehelp(subroot->left(), K, t));
else if (KEComp::gt(K, subroot->val()))
subroot->setRight(removehelp(subroot->right(), K, t));
else { // Found it: remove it
BinNode<Elem>* temp;
t = subroot;
if (subroot->left() == NULL)
subroot = subroot->right();
else if (subroot->right() == NULL)
subroot = subroot->left();else { // Both children are non-empty
subroot->setRight(deletemin(subroot->right(), temp));
Elem te = subroot->val();
subroot->setVal(temp->val());
temp->setVal(te);t = temp;
} }
return subroot;
}
Binary Search Trees: ADT
removehelp function
99
42
427
2 32
3723
25
Cannot find the target
Found the target
Searching
subroot
root
42
Bingo!RightLeft
Bingo!RightLeft
Bingo!RightLeft
99.L42.L
root
23root=removehelp(root,7,aBNode);
temp
t (aBNode)
te = 7
23
7
bool remove(const Key& K, Elem& e) {BinNode<Elem>* t = NULL;root = removehelp(root, K, t);if (t == NULL) return false;e = t->val();nodecount--;delete t;return true;
}
49
Lec 5: Binary Tree
Binary Search Trees: ADT
removehelp function
88
42 91
7
32
37
40
23
16 26 88
42 91
7
32
37
40
23
16 26
88
42 91
7
32
37
40
23
16 26 88
42 91
7
32
37
40
23
16 26
37
88
42 91
7
32
37
40
23
16 26
88
42 91
7
32
37
40
23
16 26
No Right Child
No Left Child
Have both Children
50
Lec 5: Binary Tree
Binary Search Trees: ADT
clearhelp functions
root
NULL
23
NULL NULL
19
NULL NULL
8
11
template <class Key, class Elem, class KEComp, class EEComp>
void BST<Key,Elem,KEComp,EEComp>::
clearhelp(BinNode<Elem>* subroot) {
if (subroot == NULL) return;
clearhelp(subroot->left());
clearhelp(subroot->right());
delete subroot;
}
clearhelp(root);
Base Case
Recursive Call 1
Recursive Call 2
Delete the node
void clear() {
clearhelp(root);root = NULL;
nodecount = 0;}
}
51
Lec 5: Binary Tree
template <class Key, class Elem, class KEComp, class EEComp>
void BST<Key,Elem,KEComp,EEComp>::
printhelp(BinNode<Elem>* subroot, int level) {
if (subroot == NULL) return NULL;
printhelp(subroot->left(), level+1);
for (int i=0; i<level; i++)
cout << “ “;
cout << subroot->val() << “\n”;
printhelp(subroot->right(), level+1);
}
Binary Search Trees: ADT
printhelp functions
root
NULL
23
11
NULL NULL
19
NULL NULL
8
Base Case
Recursive Call 1
Recursive Call 2
Print the node
23
8
11
19
printhelp(root, 0);
52
Lec 5: Binary Tree
☺☺☺☺ Small Quiz!!!! ☺☺☺☺
Q1. Draw the BST that results from each of the
following commands:
41
4536
90
64
55
54
78
8870
24
289 95
99
aBST.insert(54);
aBST.removeAny(temp);
aBST.remove(45, temp);
aBST.remove(36, temp);
aBST.remove(90, temp);
aBST.remove(64, temp);
aBST.removeAny(temp);
aBST.print();
aBST
53
Lec 5: Binary Tree
☺☺☺☺ Small Quiz!!!! ☺☺☺☺
aBST.insert(54);
aBST.removeAny(temp);
aBST.remove(45, temp);
aBST.remove(36, temp);
aBST.remove(90, temp);
aBST.remove(64, temp);
aBST.removeAny(temp);
aBST.print();
41
4536
54 8870
9024
64289 95
55 78 99
54
41
4536
54 8870
9024
6428 95
55 78 99
54
41
4536
54 8870
9028
64 95
55 78 99
54
41
36
54 8870
90
28 64 95
55 78 99
54
41
28
54 8870
90
64 95
55 78 99
54
41
28
54 8870
95
64 99
55 78
54
41
28
54 88
95
70 99
55 78
54
41
28
54
54
55
70
78
88
95
99
54
Lec 5: Binary Tree
Binary Search Trees: ADT
Cost of BST Operations
� Assume d = depth of the tree
� Find: Θ(d)
� Insert: Θ(d)
� Delete: Θ(d)
� d is Θ(log2 n) if tree is balanced
� The worst case: Θ(n)
� The average case: Θ(log2 n)
88
42 91
7
32
37
40
23
16 26
88
42
7
32
37
40
32
37
40
23
16 26 33
55
Lec 5: Binary Tree
Binary Tree
Array-Based Complete BT
� Simple and compact array implementation
approach for complete binary tree
� No overhead space
� Complete binary Tree is useful:
� Heap data structure
� External sorting algorithm
A
BD
CEH
GIJ
T
56
Lec 5: Binary Tree
Binary Tree
Array-Based Complete BT
0
1
4
109
3
87
2
65
11
----10--8--6--4--2--Right Sibling
--9--7--5--3--1----Left Sibling
--------------108642Right Child
------------1197531Left Child
54433221100--Parent
11109876543210Position
Parent(r) = (r - 1) / 2 if r ≠ 0 and r < n
Leftchild(r) = 2r + 1 if 2r+1 < n
Rightchild(r) = 2r + 2 if 2r +2 < n
Leftsibling(r) = r - 1 if r is even, r > 0 and r < n
Rightsibling(r) = r + 1 if r is odd, r +1 < n
57
Lec 5: Binary Tree
Heaps
� Heap is a data structure with the following properties:
� Complete Binary Tree
� Value stored in a heap are partially ordered
� There is a relationship between the value stored at any node and values of its children
� Two types of heaps
� Min-heap: All values less than or equal to child values
� Max-heap: All values greater than or equal to child values
� Heap can be implemented simply by using the array-based complete binary tree
58
Lec 5: Binary Tree
Heaps
88
85
73
60
72
486
83
5742
5
24
46
4860
25
4828
33
5742
99
Min-heap
Max-heap
59
Lec 5: Binary Tree
Heaps: ADTtemplate<class Elem,class Comp> class maxheap{
private:
Elem* Heap; // Pointer to the heap array
int size; // Maximum size of the heap
int n; // Number of elems now in heap
void siftdown(int); // Put element in place
public:
maxheap(Elem* h, int num, int max);
int heapsize() const;
bool isLeaf(int pos) const;
int leftchild(int pos) const;
int rightchild(int pos) const;
int parent(int pos) const;
bool insert(const Elem&);
bool removemax(Elem&);
bool remove(int, Elem&);
void buildHeap();
};
60
Lec 5: Binary Tree
0
43
1 2
65
6
Heaps
buildheap functionpublic void buildheap() // Heapify contents
{ for (int i=n/2-1; i>=0; i--) siftdown(i); }
template <class Elem, class Comp>
void maxheap<Elem,Comp>::siftdown(int pos) {
while (!isLeaf(pos)) {
int j = leftchild(pos);
int rc = rightchild(pos);
if ((rc<n) && Comp::lt(Heap[j],Heap[rc]))
j = rc;
if (!Comp::lt(Heap[pos], Heap[j])) return;
swap(Heap, pos, j);
pos = j;
}}
Don’t need to call siftdown on leaf nodes
--6--4--2--Right Sibling
5--3--1----Left Sibling
--------642Right Child
--------531Left Child
221100--Parent
6543210Position
6543210value
6543210Position
pos
rc
j
6 2
5
6
2
6
j
aHeap.siftdown(2);aHeap.buildheap();
aHeap.siftdown(1);aHeap.siftdown(0);
2
61
Lec 5: Binary Tree
Heaps
buildheap function1
54
2 3
76
aHeap.siftdown(2); aHeap.siftdown(0);
aHeap.siftdown(1);
1
54
2 3
76
1
54
2 7
36
1
24
5 7
36
7
24
5 1
36
aHeap.siftdown(2);aHeap.buildheap();
aHeap.siftdown(1);aHeap.siftdown(0);
7
3
5
2
7
1
6
1
62
Lec 5: Binary Tree
Heaps
removemax function
template <class Elem, class Comp>
bool maxheap<Elem, Comp>:: removemax(Elem& it) {
if (n == 0) return false; // Heap is empty
swap(Heap, 0, --n); // Swap max with end
if (n != 0) siftdown(0);
it = Heap[n]; // Return max value
return true;
}
7
34
6 5
12
aHeap.removemax(aValue);1
7
6
14
1aValue = 7
63
Lec 5: Binary Tree
Heaps
remove function
template <class Elem, class Comp>
bool maxheap<Elem, Comp>::remove(int pos, Elem& it) {
bool flag = false;
if ((pos < 0) || (pos >= n)) return false;
swap(Heap, pos, --n);
while ((pos != 0) && (Comp::gt(Heap[pos],Heap[parent(pos)])))
{
swap(Heap, pos, parent(pos));
pos = parent(pos);
flag=true;
}
if (!flag) siftdown(pos);
it = Heap[n];
return true;
}
10
32
4 9
62aHeap.remove(3, aValue); 6 2
6
4
aValue = 2
Refer to Figure 5.20, pp170
64
Lec 5: Binary Tree
template <class Elem, class Comp>
bool maxheap<Elem, Comp>::remove(int pos, Elem& it) {
bool flag = false;
if ((pos < 0) || (pos >= n)) return false;
swap(Heap, pos, --n);
while ((pos != 0) && (Comp::gt(Heap[pos],Heap[parent(pos)])))
{
swap(Heap, pos, parent(pos));
pos = parent(pos);
flag=true;
}
if (!flag) siftdown(pos);
it = Heap[n];
return true;
}
Heaps
remove function
10
78
9 4
21aHeap.remove(1, aValue);
2
9
8
2
aValue = 9
Refer to Figure 5.20, pp170
65
Lec 5: Binary Tree
Heaps
insert function
template <class Elem, class Comp> // Insert element
bool maxheap<Elem, Comp>::insert(const Elem& val) {
if (n >= size) return false; // Heap is full
int curr = n++;
Heap[curr] = val; // Start at end of heap
// Now sift up until curr's parent > curr
while ((curr!=0) && (Comp::gt(Heap[curr], Heap[parent(curr)])))
{
swap(Heap, curr, parent(curr));
curr = parent(curr);
}
return true;
}
7
24
5 6
31
94
9
9
5
9
7
aHeap.insert(9);
66
Lec 5: Binary Tree
☺☺☺☺ Small Exercise!!!! ☺☺☺☺
55
5
12 9
23
328
44 2
254
0
aH.buildHeap();
aH.removemax(temp);
aH.remove(1, temp);
aH.insert(45);
aH (maxHeap)
public void buildheap()
{
for (int i=n/2-1; i>=0; i--)
siftdown(i);
} aH.siftdown(5);
aH.siftdown(0);
…
67
Lec 5: Binary Tree
☺☺☺☺ Small Exercise!!!! ☺☺☺☺
55
5
12 9
23
328
44 2
254
0
55
5
12 9
23
328
44 54
22
0
55
5
12 9
23
328
44 54
22
0
55
5
12 9
23
328
44 54
22
0
55
5
12 9
54
328
44 23
22
0
55
5
12 9
54
328
44 23
22
0
0
5
12 9
54
328
44 23
22
55
12
5
0 9
54
328
44 23
22
55
12
0
5 9
54
328
44 23
22
55
aH.siftdown(5); aH.siftdown(2);
aH.siftdown(4);
aH.siftdown(3);
aH.siftdown(1);
aH.siftdown(0);
55
5
12 9
23
328
44 2
254
0
68
Lec 5: Binary Tree
☺☺☺☺ Small Exercise!!!! ☺☺☺☺
12
0
5 9
54
328
44 23
22
55
12
55
5 9
54
328
44 23
22
0
12
55
5 9
0
328
44 23
22
54
12
55
5 9
44
328
0 23
22
54
12
55
5 9
44
08
32 23
22
54
aH.removemax(temp);
12
5 9
44
08
32 23
22
54
69
Lec 5: Binary Tree
☺☺☺☺ Small Exercise!!!! ☺☺☺☺aH.remove(1, temp);
12
5 9
44
08
32 23
22
54
12
5 9
2
08
32 23
442
54
12
5 9
32
08
2 23
442
54
12
5 9
32
02
8 23
442
54
12
5 9
32
02
8 23
2
54
70
Lec 5: Binary Tree
☺☺☺☺ Small Exercise!!!! ☺☺☺☺
aH.insert(45);
45
12
5 9
32
02
8 23
2
54
12
5 9
32
02
8 45
232
54
12
5 9
45
02
8 32
232
54
12
5 9
45
02
8 32
232
54
71
Lec 5: Binary Tree
Heaps
� When a heap with size n is created, there are
two choices:
� Buildheap function
� Insert n values to a heap using insert function
� Which one is better?
72
Lec 5: Binary Tree
Heaps
� Time Complexity
� Insert n values to a heap
� Insert one value takes Θ(log n) in the worst case
� Move from the bottom to the top of the tree
�
� Buildheap function (n values in the array)
� Depends on number of shiftdown calls
�
2
11
5 6
1
87
3 4
109
0
12 1413
)log(log 2
1
2 nnin
i
Θ=∑=
)(2)1(
log
1
nn
in
ii
Θ=−∑=
4x1
2x2
1x3
1 2 3 4
n/2i
i-1 0 1 2 3
8 4 2 1
n=16
We should use buildheap to build the heap
73
Lec 5: Binary Tree
Heaps: Priority Queues
� A priority queue stores objects, and on
request releases the object with greatest
value
� Example:
Scheduling jobs in a multi-tasking operating
system
74
Lec 5: Binary Tree
Heaps: Priority Queues
� Possible Solutions:
� Linked List
� Insert appends to a linked list ( O(1) )
� Remove max value determines the maximum by scanning
the list ( O(n) )
� Sorted Linked List (decreasing order)
� Insert places an element in its correct position ( O(n) )
� Remove max value simply removes the head of the list
( O(1) )
� Heap
� Both insert and remove max value are O( log n ) operations
75
Lec 5: Binary Tree
Huffman Coding Trees
� An entropy encoding algorithm used for
lossless data compression
� Use a variable-length code table for
encoding a source symbol
� Derived based on the estimated probability of
occurrence for each possible value
76
Lec 5: Binary Tree
Huffman Coding Trees
� Fixed-Length Coding
� ASCII codes: 8 bits per character
� E : 0100 0101 Z : 0101 1010
� Variable-Length Coding
� Can take advantage of relative frequency of
letters to save space
120424237322472
ELDUCFKZ
Use smaller number of bits to store itUse larger number of bits to store it
77
Lec 5: Binary Tree
Huffman Coding Trees
� Build the tree with minimum
external path weight
� Combine the two smallest
values each time
2
Z
7
K
24
M
32
C
37
U
42
D
42
L
120
E
9
33
65
79
107
186
306
78
Lec 5: Binary Tree
Huffman Coding Trees
7
K
2
Z
24
M
32
C
37
U
42
D
42
L
120
E
9
33
65
79107
186
306
61111102Z
310137U
311042L
61111117K
51111024M
10120E
310042D
4111032C
BitCodeFreqLetter
1 0
1 0
1 01 0
1 0
1 0
1 0
79
Lec 5: Binary Tree
Huffman Coding Trees
� Huffman Coding has the prefix property
� No code in the set is the prefix of another
� Non-prefix example:
� A: 1 B: 110 C: 01
�What is 1101?
�More than one solutions
� Decode:
101100111011110061111102Z
310137U
311042L
61111117K
51111024M
10120E
310042D
4111032C
BitCodeFreqLetter
U D C M E
AAC BA
80
Lec 5: Binary Tree
Huffman Coding Trees
Expected Cost
� Expected Cost per letter
(how many bits have been used for a letter in average?)
61111102Z
310137U
311042L
61111117K
51111024M
10120E
310042D
4111032C
BitCodeFreqLetter
= 785/306
= 2.57
(1*120+3*121+4*32+5*24+6*9)
306
81
Lec 5: Binary Tree
Huffman Coding Trees
Huffman Node ADT
template <class Elem>
class HuffNode { // Node abstract base class
public:
virtual int weight() = 0;
virtual bool isLeaf() = 0;
virtual HuffNode* left() const = 0;
virtual void setLeft(HuffNode*) = 0;
virtual HuffNode* right() const = 0;
virtual void setRight(HuffNode*) = 0;
};
7
K
2
Z
24
M
32
C
9
33
65
82
Lec 5: Binary Tree
Huffman Coding Trees
FreqPair
template <class Elem>
class FreqPair { // An element/frequency pair
private:
Elem it; // An element of some sort
int freq; // Frequency for the element
public:
FreqPair(const Elem& e, int f) // Constructor
{ it = e; freq = f; }
~FreqPair() { } // Destructor
int weight() { return freq; } // Return the weight
Elem& val() { return it; } // Return the element
};
7
K
2
Z
24
M
32
C
9
33
65
2
Z
83
Lec 5: Binary Tree
Huffman Coding Trees
Leaf Node
template <class Elem> // leaf node subclass
class LeafNode: public HuffNode<Elem> {
private:
Freqpair<Elem>* it; // Frequency pair
public:
LeafNode(const Elem& val, int freq) //constructor
{ it = new Freqpair<Elem>(val,freq); }
int weight() { return it->weight(); } //Return frequency
Freqpair<Elem>* val() { return it; }
bool isLeaf() { return true; }
virtual HuffNode* left() const { return NULL; }
virtual void setLeft(HuffNode*) { }
virtual HuffNode* right() const { return NULL; }
virtual void setRight(HuffNode*) { }
};
7
K
2
Z
24
M
32
C
9
33
65
2
ZNULL NULL
84
Lec 5: Binary Tree
Huffman Coding Trees
Internal Nodetemplate <class Elem> //Internal node subclass
class IntlNode: public HuffNode<Elem> {
private:
HuffNode<Elem>* lc; //left child
HuffNode<Elem>* rc; //right child
int wgt; //Subtree weight
public:
IntlNode(HuffNode<Elem> * l; HuffNode<Elem> * r)
{ wgt = l->weight() + r->weight(); lc = l; rc = r; }
int weight() { return wgt; } // Return frequency
bool isLeaf() { return false; }
HuffNode<Elem>* left() const { return lc; }
void setLeft(HuffNode<Elem>* b)
{ lc = (HuffNode*)b; }
HuffNode<Elem>* right() const { return rc; }
void setRight(HuffNode<Elem>* b)
{ rc = (HuffNode*)b; }
};
7
K
2
Z
24
M
32
C
9
33
65
9
2
Z
7
K
85
Lec 5: Binary Tree
Huffman Coding Trees
Huffman Treetemplate <class Elem>
class HuffTree {
private:
HuffNode<Elem>* theRoot;
public:
HuffTree(Elem& val, int freq)
{ theRoot = new LeafNode<Elem>(val,freq);}
HuffTree(HuffTree<Elem>* l, HuffTree<Elem>* r)
{ theRoot = new IntlNode<Elem>(l->root(), r->root());}
~HuffTree() { }
HuffNode<Elem>* root() { return theRoot; }
int weight() { return theRoot->weight(); }
};
7
K
2
Z
24
M
32
C
9
33
65
86
Lec 5: Binary Tree
Huffman Coding Trees
Huffman Compare
template <class Elem> class HHCompare {
public:
static bool lt(HuffTree<Elem>* x, HuffTree<Elem>* y)
{ return x->weight() < y->weight(); }
static bool eq(HuffTree<Elem>* x, HuffTree<Elem>* y)
{ return x->weight() = = y->weight(); }
static bool gt(HuffTree<Elem>* x, HuffTree<Elem>* y)
{ return x->weight() > y->weight(); }
};
7
K
2
Z
24
M
32
C
9
33
65
87
Lec 5: Binary Tree
Huffman Coding Trees
Build Huffman Tree
template <class Elem> HuffTree<Elem>*
buildHuff(SLList<HuffTree<Elem>*,HHCompare<Elem>>* f1)
{
HuffTree<Elem>* temp1, *temp2, *temp3;
for (f1->setStart();
f1->leftLength() + f1->rightLength()>1;
f1->setStart()) { //While at least two items left
f1->remove(temp1); // Pull first two trees off the list
f1->remove(temp2);
temp3 = new HuffTree<Elem>(temp1, temp2);
f1->insert(temp3); // Put the new tree back on list
delete temp1; // Delete the remnants
delete temp2;
}
return temp3;
}
Sorted Linked List (SLL)
Element of SLL is Huffman Tree
7
K
2
Z
24
M
32
Cf1
9temp3
7
K
2
Z
temp1
temp2
Use Huffman Compare in SLL
88
Lec 5: Binary Tree
Huffman Coding Trees
Build Huffman Tree: Example
2
Z
7
K
24
M
32
C
37
U
42
D
42
L
120
E
2
Z
7
K
24
M
32
C
37
U
42
D
42
L
120
E9
32
C
37
U
42
D
42
L
120
E
2
Z
7
K
24
M9
33
37
U
42
D
42
L
120
E32
C
2
Z
7
K
24
M9
33
65
42
L
120
E32
C
2
Z
7
K
24
M9
33
65
37
U
42
D
79
120
E37
U
42
D
79
42
L32
C
2
Z
7
K
24
M9
33
65
107