+ All Categories
Home > Documents > Data Structure Chapter 5

Data Structure Chapter 5

Date post: 18-Dec-2021
Category:
Upload: others
View: 0 times
Download: 0 times
Share this document with a friend
45
Data Structure Chapter 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)
Transcript

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

89

Lec 5: Binary Tree

Huffman Coding Trees

Build Huffman Tree: Example

120

E

37

U

42

D

79

42

L32

C

2

Z

7

K

24

M9

33

65

107

186

306120

E

37

U

42

D

79

42

L32

C

2

Z

7

K

24

M9

33

65

107

186


Recommended