0% found this document useful (0 votes)
2 views

10B Tree Data Structure and Intro to Recursion

Uploaded by

Sophia Lindholm
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views

10B Tree Data Structure and Intro to Recursion

Uploaded by

Sophia Lindholm
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 23

Tree Data Structure and Intro to Recursion

Cosmin E. Oancea
[email protected]

Department of Computer Science (DIKU)


University of Copenhagen

November 2023 KOM-IT Lecture Slides


Today’s Lecture

learn what is a tree, a binary tree, and a binary search tree;

learn how to represent and build trees;

learn how to use recursive functions on trees, e.g.,


how to count the number of nodes of a tree or
how to search for a key in the trees.
What is a Tree?
A tree is a hierarchical data structure defined as a collection of
nodes. Nodes represent values and nodes are connected by edges.
A tree has the following properties:

1 The tree has one node called root. The tree originates from
this, and hence the root does not have any parent.

2 Each node other than the root has one parent only but can
have multiple children.

3 Each node is connected to its children via an edge.

4 A leaf is a node that does not have any children.

It follows that for any node, there is a unique path (in the tree)
from the root to that node.
Tree Nomenclature

The height of a tree is equal to the largest number of edges


from the root to the most distant leaf node.
A binary tree is a tree in which each node has at most two
children.
A fully-balanced binary tree of height h has 2h+1 − 1 nodes.
Tree Example: Animal Classification
Tree Example: Family Tree
Tree Example: File System
Tree Example: HTML Representation
Running Example

Ken

Lis Palle

Sarah Jens Else Christian


Building a Binary Tree

c l a s s B i n Tr e e {
data ; // t h e d a t a s t o r e d i n t h i s node
left ; // the l e f t subtree Ken
right ; // the r i g h t subtree
Lis Palle
constructor ( d , l , r ) {
t h i s . data = d ;
this . left = l ;
Sarah Jens Else Christian
this . right = r ;
}
}
Building a Binary Tree

c l a s s B i n Tr e e {
data ; // t h e d a t a s t o r e d i n t h i s node
left ; // the l e f t subtree Ken
right ; // the r i g h t subtree
Lis Palle
constructor ( d , l , r ) {
t h i s . data = d ;
this . left = l ;
Sarah Jens Else Christian
this . right = r ;
}
}

l e t ken = new B i n Tr e e ( ” Ken ” , n u l l , n u l l ) ; / / t h e r o o t

ken . r i g h t = new B i n Tr e e ( ” Pa l e ” , n u l l , n u l l ) ;
ken . r i g h t . r i g h t = new B i n Tr e e ( ” C h r i s t i a n ” , n u l l , n u l l ) ;
ken . r i g h t . l e f t = new B i n Tr e e ( ” E l s e ” , n u l l , n u l l ) ;

l e t mum = new B i n Tr e e ( ” L i s ”
, new B i n Tr e e ( ” Sarah ” , n u l l , n u l l )
, new B i n Tr e e ( ” J e n s ” , n u l l , n u l l )
);
ken . l e f t = mum;
What is a Recursive Function
A recursive function is a function that calls itself once or in
multiple places.

Divide-and-Conquer Reasoning:

split a problem into (similar) but smaller sub-problems;

assuming that I can solve (recursively) the sub-problems, it


comes down to reasoning of how to build the solution of my
problem from the partial results of sub-problems (?)

base cases: simple solutions to very small sub-problems


(that do not use recursion, i.e., end of recursion).

It is essential that the recursive sub-problems are smaller than


the original, such that the base case is eventually reached.
Otherwise the program may run forever – Example!
Counting the Number of Nodes in a Binary Tree
c l a s s B i n Tr e e {
data ; // t h e d a t a s t o r e d i n t h i s node
left ; // the l e f t subtree Ken
right ; // the r i g h t subtree
Lis Palle
constructor ( d , l , r ) {
t h i s . data = d ;
this . left = l ;
Sarah Jens Else Christian
this . right = r ;
}
}
Counting the Number of Nodes in a Binary Tree
c l a s s B i n Tr e e {
data ; // t h e d a t a s t o r e d i n t h i s node
left ; // the l e f t subtree Ken
right ; // the r i g h t subtree
Lis Palle
constructor ( d , l , r ) {
t h i s . data = d ;
this . left = l ;
Sarah Jens Else Christian
this . right = r ;
}
}

f u n c t i o n countTreeNodes ( node ) {
i f ( node === n u l l ) { / / base case
return 0;
}
l e t n u m l e f t = countTreeNodes ( node . l e f t ) ;
l e t n u m r i g h t = countTreeNodes ( node . r i g h t ) ;
return (1 + num left + num right ) ;
}
countTreeNodes ( ken ) ; / / 7
countTreeNodes (mum ) ; / / 3
Finding a Value in a Binary Tree
c l a s s B i n Tr e e {
data ; // t h e d a t a s t o r e d i n t h i s node
Ken
left ; // the l e f t subtree
right ; // the r i g h t subtree
Lis Palle
constructor ( d , l , r ) {
t h i s . data = d ;
this . left = l ; Sarah Jens Else Christian
this . right = r ;
} }

Takes time proportional with the size of the tree in the worst case.
f u n c t i o n findValInTree ( v , t r e e ) {
i f ( t r e e === n u l l ) r e t u r n false ;

i f ( t r e e . d a t a === v ) {
r e t u r n true ;
} else {
r e t u r n findValInTree ( v , t r e e . l e f t ) | |
findValInTree ( v , t r e e . r i g h t ) ;
}
}
f i n d V a l I n T r e e ( ” C h r i s t i a n ” , ken ) ; // true
f i n d V a l I n T r e e ( ” John ” , ken ) ; // false
What is a Binary Search Tree?
A binary search tree is a binary tree with the additional properties:

1 The left subtree of any node contains only nodes with keys
lesser than that node’s key.

2 The right subtree of any node contains only nodes with keys
greater than that node’s key.

3 The left and right subtrees of any node must also be binary
search trees.
How to Build a Binary Search Tree?
Building a Binary Search Tree
c l a s s B i n Tr e e {
data ; // t h e d a t a s t o r e d i n t h i s node
left ; // the l e f t subtree
right ; // the r i g h t subtree

constructor ( d , l , r ) {
t h i s . data = d ;
this . left = l ;
this . right = r ;
} }

f u n c t i o n insertInBST ( v , t r e e ) {
i f ( t r e e === n u l l ) { / / base case
r e t u r n new B i n Tr e e ( v , n u l l , n u l l ) ;
}
i f ( t r e e . d a t a === v ) { / / base case
return tree ;
}
i f ( t r e e . data > v ) {
t r e e . l e f t = insertInBST ( v , t r e e . l e f t ) ; // recursion
} else { / / ( t r e e . data < v )
t r e e . r i g h t = insertInBST ( v , t r e e . r i g h t ) ; / / r e c u r s i o n
}
return tree ;
}
Building a Binary Search Tree
c l a s s B i n Tr e e {
data ; // t h e d a t a s t o r e d i n t h i s node
left ; // the l e f t subtree
right ; // the r i g h t subtree

constructor ( d , l , r ) {
t h i s . data = d ;
this . left = l ;
this . right = r ;
} }

let bst = insertInBST (25 , null ) ; / / root


bst = insertInBST (20 , insertInBST (36 , bst ) ) ; / / l e ve l 1
bst = insertInBST (10 , insertInBST (22 , bst ) ) ; / / l e ve l 2
bst = insertInBST (30 , insertInBST (40 , bst ) ) ;
bst = insertInBST ( 5 , insertInBST (12 , bst ) ) ; // level 3
bst = insertInBST (28 , insertInBST (38 , insertInBST (48 , bst ) ) ) ;
Finding a Value in a Binary Search Tree
c l a s s B i n Tr e e {
data ; // t h e d a t a s t o r e d i n t h i s node
left ; // the l e f t subtree
right ; // the r i g h t subtree

constructor ( d , l , r ) {
t h i s . data = d ;
this . left = l ;
this . right = r ;
} }

Takes time proportional with the logarihm of the number of


nodes in the tree, if the tree is balanced.
(At worst it traverses the longest path from the root to a leaf.)
f u n c t i o n findValInBST ( v , t r e e ) {
i f ( t r e e === n u l l ) { r e t u r n false ; } / / b a s e c a s e
i f ( t r e e . d a t a === v ) { r e t u r n true ; } / / b a s e c a s e

i f ( t r e e . d a t a > v ) { r e t u r n findValInBST ( v , t r e e . l e f t ) ; } / / r e c u r s i o n
else { r e t u r n findValInBST ( v , t r e e . r i g h t ) ; } / / r e c u r s i o n
}
fi nd Val In BST ( 4 8 , bst ) ; // true
fi nd Val In BST ( 2 9 , bst ) ; // false
How to Represent a Tree (Not Binary)

c l a s s Tr e e {
data ; / / t h e d a t a s t o r e d i n t h i s node
children ; / / an a r r a y o f c h i l d r e n n o d e s

c o n s t r u c t o r ( d , ch s ) {
t h i s . data = d;
t h i s . c h i l d r e n = ch s ;
} }

What tree does the code below constructs?


leaf 3 = new Tr e e ( 3 , []);
leaf 4 = new Tr e e ( 4 , []);
leaf 5 = new Tr e e ( 5 , []);
leaf 6 = new Tr e e ( 6 , []);
leaf 7 = new Tr e e ( 7 , []);
node 2 = new Tr e e ( 2 , [ leaf 5 , leaf 6 , leaf 7 ] ) ;
root = new Tr e e ( 1 , [ node 2 , l e a f 3 , l e a f 4 ] ) ;
How to Build a File-System Tree?

class Folder { class Textfile {


name ; // string name ; // string
children ; / / array of Folder co n t e n t ; / / ( b i g g e r ) s t r i n g
/ / or T e x t f i l e objs
c o n s t r u c t o r ( nm , a r r ) { c o n s t r u c t o r ( nm , s t r ) {
t h i s . name = nm ; t h i s . name = nm ;
t h i s . children = arr ; t h i s . co n t e n t = s t r ;
} }
isFile () { isFile () {
r e t u r n false ; r e t u r n true ;
} }
} }

f i l e 1 = new T e x t f i l e ( ” f i l e 1 . t x t ” , ”Some t e x t 1 ” ) ;
f i l e 2 = new T e x t f i l e ( ” f i l e 2 . t x t ” , ”Some t e x t 2 ” ) ;
workd = new F o l d e r ( ” Work ” , []);
r o o t = new F o l d e r ( ”home ” , [ f i l e 1 , workd , f i l e 2 ] ) ;

What kind of tree does the code above produce?


Summary
We have learned what trees, binary trees and binary search trees
are, and how to manipulate them:

how to use objects and arrays to build trees;

how to write recursive functions that traverse trees, e.g.,


I searching for a key in a binary search tree;
I counting the number of nodes in a tree.

You might also like