0% found this document useful (0 votes)
20 views82 pages

07 Tree-1

The document discusses trees and their implementation in C++. It defines a tree as a collection of nodes where each node has zero or more subtrees connected by edges from the root node. It describes tree properties like height, depth, ancestors and descendants. It also discusses various tree traversal algorithms like preorder, inorder and postorder and their applications. Binary trees are introduced as trees where each node has at most two children. Binary search trees and their operations are also briefly mentioned.

Uploaded by

farhan khan
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
20 views82 pages

07 Tree-1

The document discusses trees and their implementation in C++. It defines a tree as a collection of nodes where each node has zero or more subtrees connected by edges from the root node. It describes tree properties like height, depth, ancestors and descendants. It also discusses various tree traversal algorithms like preorder, inorder and postorder and their applications. Binary trees are introduced as trees where each node has at most two children. Binary search trees and their operations are also briefly mentioned.

Uploaded by

farhan khan
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
You are on page 1/ 82

Trees

1
Outline
• Preliminaries
– What is Tree?
– Implementation of Trees using C++
– Tree traversals and applications
• Binary Trees
• Binary Search Trees
– Structure and operations
– Analysis
• AVL Trees
2
What is a Tree?
• A tree is a collection of nodes with the following properties:
– The collection can be empty.
– Otherwise, a tree consists of a distinguished node r, called root, and
zero or more nonempty sub-trees T1, T2, … , Tk, each of whose roots
are connected by a directed edge from r.
• The root of each sub-tree is said to be child of r, and r is the
parent of each sub-tree root.
• If a tree is a collection of N nodes, then it has N-1 edges.

root

T1 T2 ... Tk
3
Preliminaries
A

B C D E F G

H I J K L M N

P Q

– Node A has 6 children: B, C, D, E, F, G.


– B, C, H, I, P, Q, K, L, M, N are leaves in the tree above.
– K, L, M are siblings since F is parent of all of them.

4
Preliminaries (continued)
• A path from node n1 to nk is defined as a sequence of nodes
n1, n2, …, nk such that ni is parent of ni+1 (1 ≤i < k)
– The length of a path is the number of edges on that path.
– There is a path of length zero from every node to itself.
– There is exactly one path from the root to each node.
• The depth of node ni is the length of the path from root to
node ni
• The height of node ni is the length of longest path from
node ni to a leaf.
• If there is a path from n1 to n2, then n1 is ancestor of n2, and
n2 is descendent of n1.
– If n1 ≠ n2 then n1 is proper ancestor of n2, and n2 is
proper descendent of n1.
5
Figure 1
A tree, with height and depth information

6
Implementation of Trees
A element
struct
structTreeNode
TreeNode{{
firstChild
Object
Object element;
element;
NULL nextSibling
struct
struct TreeNode*firstChild;
TreeNode *firstChild;
struct
structTreeNode
TreeNode*nextSibling;
*nextSibling; B C D
};
}; NULL NULL

H
A NULL
NULL

B C D E F G

H I J K L M N

P Q
7
Figure 2: The Unix directory with file sizes

8
Listing a directory
// Algorithm (not a complete C++ code)
listAll ( struct TreeNode *t, int depth)
{
printName ( t, depth );
if (isDirectory())
for each file c in this directory (for each child)
listAll(c, depth+1 );
}

• printName() function prints the name of the object after


“depth” number of tabs -indentation. In this way, the
output is nicely formatted on the screen.

9
Listing a directory
// Algorithm (not a complete C++ code)
listAll ( struct TreeNode *t, int depth)
{
printName ( t, depth );
if (isDirectory())
for each file c in this directory (for each child)
listAll(c, depth+1 );
}

• printName() function prints the name of the object after “depth”


number of tabs -indentation. In this way, the output is nicely
formatted on the screen.
• The work at a node is done before processing each child of that
node.
– Here, the nodes are visited according to preorder traversal strategy.
– Root-left-right for binary trees (2 or less children)
– Similarly, inorder: left-Root-right; postorder: left-right-Root
• Location of Root matters

10
Figure 3: The directory listing for the tree shown in Figure 2

11
Size of a directory
int FileSystem::size (struct TreeNode *t) const
{
int totalSize = sizeOf(t);

if (isDirectory())
for each file c in this directory (for each child)
totalSize = totalSize + size(c);
return totalSize;
}

12
Size of a directory
int FileSystem::size (struct TreeNode *t) const
{
int totalSize = sizeOf(t); //Root not finished ‘till return reached

if (isDirectory())
for each file c in this directory (for each child)
totalSize = totalSize + size(c);
return totalSize;
}

•The nodes are visited using postorder strategy.


•The work at a node is done after processing each
child of that node.
– left-right-Root (if it was a binary tree)
13
Figure 18.9
A trace of the size method

14
Preorder Traversal
• A traversal visits the nodes of a tree
in a systematic manner
Algorithm preOrder(v)
• In a preorder traversal, a node is visit(v)
visited before its descendants for each child w of v
• Application: print a structured preorder (w)
document
Root-left-right
Make Money Fast!
1 (for binary trees)
2 5 9
1. Motivations 2. Methods References

6 7 8
3 4
2.1 Stock 2.2 Ponzi 2.3 Bank
1.1 Greed 1.2 Avidity
Fraud Scheme Robbery

15
Postorder Traversal
• In a postorder traversal, a node is Algorithm postOrder(v)
visited after its descendants
for each child w of v
• Application: compute space used
by files in a directory and its postOrder (w)
subdirectories visit(v)
9 left-right-Root
cs16/
(for binary trees)
8
3 7
todo.txt
homeworks/ programs/
1K

1 2 4 5 6
h1c.doc h1nc.doc DDR.java Stocks.java Robot.java
3K 2K 10K 25K 20K

16
Inorder Traversal
• In an inorder traversal, left node is Algorithm inOrder(v)
visited followed by the Root
followed by the right node (binary) if(v == NULL) return
• Application: fast sorting on binary inOrder (v.left)
search trees visit(v)
4 inOrder (v.right)
80
left-Root-right
2 7 (applicable to only
40 100 binary trees only)

1 3
5 8
20 50 90 120

6 95
17
( A*B+C)$F

• Draw a tree

18
Binary Trees
• A binary tree is a tree in which no node can have more
than two children
• The depth can be as large as N-1 in the worst case.

root
A binary tree consisting
of a root and
two subtrees TL and TR,
TR
both of which could
TL possibly be empty.

The depth of node ni is the length of the path from


root to node ni
The height of node ni is the length of longest path 19
Non-binary tree
from node ni to a leaf.
Binary Tree Terminology
Left Child – The left child of node n is a node directly below
and to the left of node n in a binary tree.
Right Child – The right child of node n is a node directly
below and to the right of node n in a binary tree.
Left Subtree – In a binary tree, the left subtree of node n is
the left child (if any) of node n plus its descendants.
Right Subtree – In a binary tree, the right subtree of node n is
the right child (if any) of node n plus its descendants.

20
Binary Tree -- Example

• A is the root.
A • B is the left child of A, and
C C is the right child of A.
B
• D doesn’t have a right child.
E • H doesn’t have a left child.
D
• B, F, G and I are leaves.
F G H

I

21
Binary Tree – Representing Algebraic
Expressions

Preorder traversal: left-Root-right 22


Height of Binary Tree
• The height of a binary tree T can be defined recursively as:
– If T is empty, its height is -1.
– If T is non-empty tree, then since T is of the form

TL TR

the height of T is 1 greater than the height of its root’s taller


subtree; i.e.

height(T) = 1 + max{height(TL), height(TR)}

23
Height of Binary Tree (cont.)

Binary trees with the same nodes but different heights


24
Maximum and Minimum Heights of a Binary Tree

• The maximum height of a binary tree with N nodes is N-1.


• Each level of a minimum height tree, except the last level,
must contain as many nodes as possible.

A maximum-height binary tree


with seven nodes Some binary trees of height 2
25

All but (a) is minimum-height


Some Height Theorems
Theorem 1: The maximum number of nodes that a binary
tree of height h can have is 2h+1-1.

Theorem 2: The minimum height of a binary tree with N


nodes is log2(N+1)-1 .

Let’s prove these two theorems.

26
Counting the nodes in a binary tree
Height
--------

0
Theorem 1:
N = 20 + 21 + 22 + .. + 2h-1+ 2h
1 = 1*(1-2h+1) / (1-2) = 2h+1-1
First line is a geometric series
2
where a=1, r=2, n=h+1
3

h-1
27

h
Counting the nodes in a binary tree
Height
--------

0
Theorem 1:
N = 20 + 21 + 22 + .. + 2h-1+ 2h
1 = 1*(1-2h+1) / (1-2) = 2h+1-1
2
This is the max # of nodes for
3 height h, as we cannot insert one
node without increasing the height.
So, in general N <= 2h+1-1

h-1
28

h
Counting the nodes in a binary tree
Height
--------

0
Theorem 2:
N = 2h+1-1
1 N+1=2h+1 //take logs of sides
2
log(N+1) = log(2h+1) = h+1
h = log(N+1)-1
3
This is the minimum height when
N+1 is a power of 2.
Height does not change when
some nodes missing at the last
level, e.g., N+1=13 instead of 16.
Same h must be produced there.
h-1 So, in general h = log2(N+1)-1
29

h
Number of Binary trees with Same # of Nodes

n=0  empty tree


(1 tree)

n=1 

n=2 
  (2 trees)
 

n=3 
(? trees)

30
Number of Binary trees with Same # of Nodes

n=0  empty tree


(1 tree)

n=1 

n=2 
  (2 trees)
 

n=3      
      (5 trees)
   

31
Full Binary Tree
• In a full binary tree a tree in which every node in the tree
has either 0 or 2 children

32
Full Binary Tree – Example

A full binary tree of height 2

33
Complete Binary Tree
• In a complete binary tree every level, except possibly the
last, is completely filled, and all nodes in the last level are
as far left as possible

34
Complete Binary Tree – Example

35
Full but Not Complete
Binary Tree – Example

36
Neither Full Nor Complete
Binary Tree – Example

37
Full and Complete
Binary Tree – Example

38
Balanced Binary Tree
• A binary tree is height balanced (or balanced), if the
height of any node’s right subtree differs from the height
of the node’s left subtree by no more than 1.
• A complete binary tree is a balanced tree.
• Other height balanced trees:
– AVL trees //binary search tree (BST)
– Red-Black trees //binary search tree
– B-trees //generalization of a BST (3+ children allowed)
....

39
A Pointer-Based Implementation of Binary Trees

struct BinaryNode {
Object element;
struct BinaryNode *left;
struct BinaryNode *right;
};

40
Binary Tree Traversals
• Preorder Traversal
– the node is visited before its left and right subtrees,

• Postorder Traversal
– the node is visited after both subtrees.

• Inorder Traversal
– the node is visited between the subtrees,
– Visit left subtree, visit the node, and visit the right
subtree.

41
Binary Tree Traversals

42
Preorder
void preorder(struct tree_node * p)
{ if (p !=NULL) {
cout << p->data << endl;
preorder(p->left_child);
preorder(p->right_child);
}
}

43
Inorder
void inorder(struct tree_node *p)
{ if (p !=NULL) {
inorder(p->left_child);
cout << p->data << endl;
inorder(p->right_child);
}
}

44
Postorder
void postorder(struct tree_node *p)
{ if (p !=NULL) {
postorder(p->left_child);
postorder(p->right_child);
cout << p->data << endl;
}
}

45
Finding the maximum value in a binary tree
int FindMax(struct tree_node *p)
{
int root_val, left, right, max;
max = -1; // Assuming all values are positive integers

if (p!=NULL) {
root_val = p -> data;
left = FindMax(p ->left_child);
right = FindMax(p->right_child);

// Find the largest of the three values.


if (left > right)
max = left;
else
max = right;
if (root_val > max)
max = root_val;
}
return max;
}
46
Adding up all values in a Binary Tree
int add(struct tree_node *p)
{

if (p == NULL)
return 0;
else
return (p->data + add(p->left_child)+
add(p->right_child));
}

47
Exercises
1. Write a function that will count the leaves
of a binary tree.
2. Write a function that will find the height
of a binary tree.
3. Write a function that will interchange all
left and right subtrees in a binary tree.

48
Binary Search Trees
• An important application of binary trees is their
use in searching.
• Binary search tree is a binary tree in which
every node X contains a data value that satisfies
the following:
a) all data values in its left subtree are smaller than the
data value in X
b) the data value in X is smaller than all the values in its
right subtree.
c) the left and right subtrees are also binary search tees.

49
Example
6 6

2 8 2 8

1 4 1 4

3 3 7

A binary search tree Not a binary search tree, but a


binary tree
50
Binary Search Trees – containing same data

51
Operations on BSTs
• Most of the operations on binary trees are
O(logN).
– This is the main motivation for using binary
trees rather than using ordinary lists to store
items.
• Most of the operations can be implemented
using recursion.
– we generally do not need to worry about
running out of stack space, since the average
depth of binary search trees is O(logN).
52
The BinaryNode class
template <class T>
class BinaryNode
{
T element; // this is the item stored in the node
BinaryNode *left;
BinaryNode *right;

BinaryNode( const T & theElement, BinaryNode *lt,


BinaryNode *rt ) : element( theElement ), left( lt ),
right( rt ) { }
};

53
find
/**
* Method to find an item in a subtree.
* x is item to search for.
* t is the node that roots the tree.
* Return node containing the matched item.
*/
template <class T>
BinaryNode<T> *
find( const T & x, BinaryNode<T> *t ) const
{
if( t == NULL )
return NULL;
else if( x < t->element )
return find( x, t->left );
else if( t->element < x )
return find( x, t->right );
else
return t; // Match
}

54
findMin (recursive implementation)
/**
* method to find the smallest item in a subtree t.
* Return node containing the smallest item.
*/
template <class T>
BinaryNode<T> *
findMin( BinaryNode<T> *t ) const
{
if( t == NULL )
return NULL;
if( t->left == NULL )
return t;
return findMin( t->left );
}

55
findMax (nonrecursive implementation)
/**
*method to find the largest item in a subtree t.
*Return node containing the largest item.
*/
template <class T>
BinaryNode<T> *
findMax( BinaryNode<T> *t ) const
{
if( t != NULL )
while( t->right != NULL )
t = t->right;
return t;
}

56
Insert operation
Algorithm for inserting X into tree T:
– Proceed down the tree as you would with
a find operation.
– if X is found
do nothing, (or “update” something)
else
insert X at the last spot on the path traversed.

57
Insert 5

Example
6

2 8

1 4

3 5

• What about duplicates?

58
Insertion into a BST
/* method to insert into a subtree.
* x is the item to insert.
* t is the node that roots the tree.
* Set the new root.
*/
template <class T>
void insert( const T & x,
BinaryNode<T> * & t ) const
{
if( t == NULL )
t = new BinaryNode<T>( x, NULL, NULL );
else if( x < t->element )
insert( x, t->left );
else if( t->element < x )
insert( x, t->right );
else
; // Duplicate; do nothing
}

59
Deletion operation
There are three cases to consider:
1. Deleting a leaf node
• Replace the link to the deleted node by NULL.
2. Deleting a node with one child:
• The node can be deleted after its parent adjusts a
link to bypass the node.
3. Deleting a node with two children:
• The deleted value must be replaced by an existing
value that is either one of the following:
– The largest value in the deleted node’s left subtree
– The smallest value in the deleted node’s right subtree.

60
Deletion – Case1: A Leaf Node
To remove the leaf containing the item, we have to set the pointer in its parent to NULL.

Delete 70 (A leaf node)


50 50


40 60 40 60

30 45 70 30 45

42 42

61
Deletion – Case2: A Node with only a left child
Delete 45 (A node with only a left child)
50 50

40 60
40 60

30 45 70
30 42 70

42

62
Deletion – Case2: A Node with only a right child

Delete 60 (A node with only a right child)


50
50

40 60  40 70

70 30 45
30 45

42
42

63
Deletion – Case3: A Node with two children
• Locate the inorder successor of the node.
• Copy the item in this node into the node which contains the item which will be deleted.
• Delete the node of the inorder successor.

Delete 40 (A node with two children)

50 50

40 60 
42 60

30 45 70

30 45 70

42

64
Deletion – Case3: A Node with two children

65
Deletion routine for BST
template <class T>
void remove( const T & x,
BinaryNode<T> * & t ) const
{
if( t == NULL )
return; // Item not found; do nothing
if( x < t->element )
remove( x, t->left );
else if( t->element < x )
remove( x, t->right );
else if( t->left != NULL && t->right != NULL {
t->element = findMin( t->right )->element;
remove( t->element, t->right );
}
else {
BinaryNode<T> *oldNode = t;
t = ( t->left != NULL ) ? t->left : t->right;
delete oldNode;
}
}

66
Analysis of BST Operations
• The cost of an operation is proportional to
the depth of the last accessed node.
• The cost is logarithmic for a well-balanced
tree, but it could be as bad as linear for a
degenerate tree.
• In the best case we have logarithmic access
cost, and in the worst case we have linear
access cost.

67
Minimum Height
• Insertion in search-key order produces a
maximum-height binary search tree.
• Insertion in random order produces a near-
minimum-height binary search tree.
• That is, the height of an n-node binary search
tree is:
– Best Case – log2(n+1)-1 (see slide 25)  O(log2n)
– Worst Case – n-1  O(n)
– Average Case – close to log2(n+1)-1  O(log2n)
• In fact, 1.39log2n
68
Figure 19.19
(a) The balanced tree has a height of log N; (b) the unbalanced tree has a
height of N – 1. We will study balanced binary search trees next week.

69
Number of BSTs

Suppose we’re inserting n items into an empty binary search tree to create a
binary search tree with n nodes,
 How many different binary search trees with n nodes, and
 What are their probabilities,

There are n! different orderings of n keys.


But how many different binary search trees with n nodes?

n=0  1 BST (empty tree)


n=1  1 BST (a binary tree with a single node)
n=2  2 BSTs
n=3  5 BSTs

70
Number of BSTs

    
n=3       
   
Probabilities: 1/6 1/6 2/6 1/6 1/6
Insertion Order: 3,2,1 3,1,2 2,1,3 1,3,2 1,2,3
2,3,1

In general, given n elements, the number of binary search trees that can be made
from those elements is given by the nth Catalan Number (denoted Cn).

(2n)!
Cn = ----------
(n+1)!n!
71
Number of BSTs
• A cool algorithm for counting. We know n = 0 or 1  count=1.
• Consider n=6 to see the pattern clearly.

1 2 3 .. 6
\ / \ / \ /
[2,3,4,5,6] [1] [3,4,5,6] [1,2] [4,5,6] [1,2,3,4,5]

Root=3 case, for instance, creates 2*3 = 6 BSTs (product rule).


int nBST(int n) {
if (n == 0 || n == 1) return 1;
int count = 0;
for i=1; i<=n; i++
count += nBST(i-1) * nBST(n-i); //product rule
return count; }

72
Number of BSTs
• A cool algorithm for counting. We know n = 0 or 1  count=1.
• Consider n=6 to see the pattern clearly.

1 2 3 .. 6
\ / \ / \ /
[2,3,4,5,6] [1] [3,4,5,6] [1,2] [4,5,6] [1,2,3,4,5]

Speedup by avoiding recomputations via dynamic programming


int nBST(int n, int* results) { //results inited to -1s
if (n == 0 || n == 1) return 1;
int count = 0;
for i=1; i<=n; i++
if (results[i-1]==-1) results[i-1] = nBST(i-1);
if (results[n-i]==-1) results[n-i] = nBST(n-i);
count += results[i-1] * results[n-i]; //product rule
return count; }

73
Number of BSTs
• A cool algorithm for counting. We know n = 0 or 1  count=1.
• Consider n=6 to see the pattern clearly.

1 2 3 .. 6
\ / \ / \ /
[2,3,4,5,6] [1] [3,4,5,6] [1,2] [4,5,6] [1,2,3,4,5]

Same dynamic programming w/o any recursion (cleaner code)


int nBST(int n) {
results[0] = results[1] = 1;
for i=2; i<=n; i++
results[i] = 0;
for j=0; j<i; j++
results[i] += results[j] * results[i-j-1];//prdct rule
return results[i]; }
//r[5] = r[0]*r[4] + r[1]*r[3] + r[2]*r[2] + r[3]*r[1] + r[4]*r[0] = 42

74
Order of Operations on BSTs

75
Treesort
• We can use a binary search tree to sort an array.

treesort(inout anArray:ArrayType, in n:integer)


// Sorts n integers in an array anArray
// into ascending order
Insert anArray’s elements into a
binary search tree bTree

Traverse bTree in inorder.


As you visit bTree’s nodes, copy their data items
intosuccessive locations of anArray

76
Treesort Analysis
• Inserting an item into a binary search tree:
– Worst Case: O(n)
– Average Case: O(log2n)
• Inserting n items into a binary search tree:
– Worst Case: O(n2)  (1+2+...+n) = O(n2)
– Average Case: O(n*log2n)
• Inorder traversal and copy items back into array  O(n)
• Thus, treesort is
 O(n2) in worst case, and
 O(n*log2n) in average case.
• Treesort makes exactly the same comparisons of keys as quicksort
when the pivot for each sublist is chosen to be the first key.

77
Saving a BST into a file, and
restoring it to its original shape
• Save:
– Use a preorder traversal to save the nodes of the BST into a
file.

• Restore:
– Start with an empty BST.
– Read the nodes from the file one by one, and insert them into
the BST.

78
Saving a BST into a file, and
restoring it to its original shape

Preorder: 60 20 10 40 30 50 70

79
Saving a BST into a file, and
restoring it to a minimum-height BST
• Save:
– Use an inorder traversal to save the nodes of the BST into a
file. The saved nodes will be in ascending order.
– Save the number of nodes (n) in somewhere.

• Restore:
– Read the number of nodes (n).
– Start with an empty BST.
– Read the nodes from the file one by one to create a minimum-
height binary search tree.

80
Building a minimum-height BST
readTree(out treePtr:TreeNodePtr, in n:integer)
// Builds a minimum-height binary search tree for n sorted
// values in a file. treePtr will point to the tree’s root.

if (n>0) {
// construct the left subtree
treePtr = pointer to new node with NULL child pointers
readTree(treePtr->leftChildPtr, n/2)

// get the root


Read item from file into treePtr->item

// construct the right subtree


readTree(treePtr->rightChildPtr, (n-1)/2)
}

81
A full tree saved in a file by using inorder traversal

82

You might also like