Title: Chapter 9 Trees
1Chapter 9Trees
- CS 260 Data Structures
- Indiana University Purdue University Fort Wayne
- Mark Temte
2Trees
- The binary tree is our first non-linear data
structure - A binary tree is a special case of a general tree
root
root
leaf
leaf
leaf
leaf
leaf
leaf
a binary tree
a general tree
3Tree terminology
- Node
- Usually contains data
- Root
- Typically drawn at the top
- Leaf
- Child node
- Parent node
- Root has no parent
4Tree terminology
- Binary tree
- Each node has two or fewer children
- Child nodes are left and right
- Empty tree
- No nodes
- Sibling nodes
- Same parent
- Ancestor node
- Descendent node
is different from
5Tree terminology
- Subtree
- Any node together with all of its descendants
- Depth of a node
- The number of ancestors, including the root
- Depth of root 0
- Depth of a tree
- Maximum leaf depth
- Empty tree has depth -1
6Extra terminology for binary trees
- Left child and right child
- Left subtree and right subtree
- Full binary tree
- Each leaf has the same depth
- Every non-leaf has two children
- A full binary tree of depth d has 2d1-1 nodes
a full binary tree
7Extra terminology for binary trees
- Complete binary tree
- Like a full binary tree except nodes may be
missing from the right side of the deepest level
a complete binary tree
missing nodes
8Tree representation
- Binary trees may be represented using . . .
- Arrays
- This is only practical for complete binary trees
- Pointers
- Each node has two pointers
9Array representation of binary trees
- Suppose each node contains one character
- char a new char n
// n is the number of nodes - Store root in a 0
- Store left child of a i in a 2i 1
- Store right child of a i in a 2i 2
- Parent of a i is in a ( i-1 ) / 2
// int division
A
B
C
0 1 2 3 4 5 6 7 8 9
a
D
E
F
G
H
I
J
10Array representation of binary trees
- A partially-filled array is perfect data
representation for a complete binary tree - State
- private char data
- private int manyNodes
- A new node is added to the tree at the next
available position on the deepest level - This corresponds to array position given by
manyNodes - It is possible to ensureCapacity when needed
0 1 2 3 4 5 6 7 8
9 10 11
data
manyNodes
11Array representation of binary trees
- A similar technique could be used for binary
trees that are not complete
A
B
C
char data new char n boolean
filled new boolean n
D
E
F
G
H
J
I
0 1 2 3 4 5 6 7 8
9 10 11 12 13 14 15 16 17
data
0 1 2 3 4 5 6 7 8
9 10 11 12 13 14 15 16 17
filled
12Array representation of binary trees
- If the binary tree is not complete, the array
representation has poor space efficiency - If node J had a right child, the capacity would
have to increase from 15 to 31 - The index of the right child would be 30 ( 214
2) - If the nodes contain Object data, then null can
be used for each missing child - No need for the Boolean array in this case
13Pointer representation of binary trees
class BTNode private Object data
private BTNode left private BTNode right
A
B
C
D
E
F
root
- In addition to left and right pointers, parent
pointers and sibling pointers could be added
14Behavior of the BTNode class
- Behavior
- BTNode (constructor with parameters for data,
left, and right) - getData
- getLeft and getRight
- setData
- setLeft and setRight
- getLeftmostData and getRightmostData
- removeLeftmost and removeRightmost
- isLeaf
- treeCopy
- treeSize
- Various traversal methods
15The leftmost and rightmost nodes
- To find the leftmost node of a binary tree, start
at the root and iteratively follow left pointers
until a left pointer is null - The final node in this sequence is the leftmost
node - To find the rightmost node of a binary tree,
start at the root and iteratively follow right
pointers until a right pointer is null - The final node in this sequence is the rightmost
node
16Tree traversal
- Tree traversal is the name used for iterating
over a tree - Each node must be visited exactly once in a
systematic way - There are three common techniques
- Preorder (or NLR)
- Inorder (or LNR)
- Postorder (or LRN)
- Each traversal technique is best implemented with
a recursive method
17Tree traversal examples
- Traverse the tree in each of the traversal orders
- Preorder
- A B D C E G F H I
- Inorder
- D B A E G C H F I
- Postorder
- D B G E H I F C A
root
A
B
C
D
F
E
G
G
H
I
18Tree traversal
- Assume that visit( ) is a method to be applied to
the data in each node when it is visited by the
iterator - What changes are needed for inorder and postorder
traversals? - What is the big-O of the tree traversal methods?
public void preorder( ) data.visit()
if ( left ! null ) left.preorder()
if ( right ! null )
right.preorder()
19Implementation of BTNode methods
public boolean isLeaf( ) return ( left
null ) ( right null )
public static int treeSize( BTNode root )
if ( root null ) return 0
else return 1 treeSize( root.left )
treeSize( root.right )
Note Big-O of treeSize is linear !
public Object getLeftmostData( ) if (
left null ) return data else
return left.getLeftmostData( )
20Implementation of BTNode methods
public BTNode removeLeftmost( ) if ( left
null ) return right else
left left.removeLeftmost( )
return this
- The BTNode this method returns is a pointer
to a tree with the leftmost node removed
B
A
C
B
B
D
C
21Using removeLeftmost
- Use of removeLeftmost is not restricted to the
leftmost node of the entire tree - The code below removes node F from the tree
root
A
B
C
E
D
F
G
H
root.setRight( root.getRight().removeLeftmost() )
I
J
22Displaying a tree with indentation
- The goal is to display the tree below using
indentation as indicated
A B D E
G -- C --
F H I
root
A
B
C
D
F
E
G
G
H
I
23Displaying a tree with indentation
public void print( int depth ) int i
for ( i 1 i lt depth i )
System.out.print( " )
System.out.println( data ) if ( left !
null ) left.print( depth1 ) else
if ( right ! null ) for ( i 1 i lt
depth1 i ) System.out.print( "
) System.out.println( "-- )
if ( right ! null )
right.print( depth1 ) else if ( left !
null ) for ( i 1 i lt depth1 i
) System.out.print( " )
System.out.println( "-- )
A B D E
G -- C --
F H I
24Tree applications
- A binary taxonomy tree can be used to represent
certain kinds of knowledge - Read about binary taxonomy trees
- Textbook, pages 438 439
- Read about an animal guessing application
- Textbook, pages 454 464
25The binary search tree (BST)
- Consider implementing a key-value table
- Using an array, the table look-up operation can
have logarithmic performance if the key-value
pairs are stored in ascending order of the keys - A binary search is possible
- But insertion and deletion operations have only
linear performance - If key-value pairs are stored unordered using an
array or a linked list, then . . . - Insertion has constant time performance
- But the look-up and deletion operations have only
linear performance
26The binary search tree (BST)
- A binary search tree provides an implementation
of a table combining logarithmic look-up with
logarithmic insertion and deletion operations - As in the case of an array with binary search,
total order semantics is needed - Operations lt, gt, lt, gt, , and !
The BST property At any node n, all nodes l in
ns left subtree have l lt n and all nodes r in
ns right subtree have r gt n
27The binary search tree (BST)
- Store the following values in a BST
- J, D, G, M, F, Q, B, N
- Does the BST property hold at each node?
- How do you search for a node?
- If you search for G, do you find it?
- If you search for H, what happens?
root
J
D
M
B
Q
G
F
G
N
28BSTs
- If a BST is traversed using an inorder (LNR)
traversal, then the nodes are visited in
ascending order - What is the maximum number of comparisons needed
to search for an element in a BST or to insert an
element? - Answer maximum comparisons depth 1
29BST performance
- A binary tree is balanced if, at each node n, the
depths of ns left and right subtrees differ by 0
or 1 - The depth of a balanced binary tree with n nodes
is O( log(n) ) - Search performance
- Best case logarithmic performance O( log(n) )
- When the tree is balanced
- Worse case linear performance O( n )
- When the BST is built, say, from nodes that
arrive in ascending order
30Balanced binary trees
- An unbalanced tree may be balanced by using the
AVL algorithm - Algorithm created by Adelson, Velskii, and
Landis - A study of the details of the AVL algorithm is
beyond the scope of the course - However, the algorithm relies on two basic
operations - Single rotation
- Double rotation
31The AVL single rotation
- A single rotation is used when an outside subtree
is too tall - The single rotation
- Decreases the depth of CL
- Increases the depth of PR
C
P
C
P
CL
PR
CL
CR
CR
PR
32The AVL double rotation
- A double rotation is used when an inner subtree
is too tall - The double rotation
- Decreases the depth of GL and GR
- Increases the depth of PR
P
G
C
P
C
PR
G
CL
GR
PR
CL
GL
GL
GR
33The IntTreeBag class
- The IntTreeBag class implements the Bag ADT using
a BST - Assume that the BST is always kept in balance
- State
- private IntBTNode root
34Some IntTreeBag methods
public void add( int element ) if ( root
null ) root new IntBTNode( element,
null, null ) else Descend from
the root until the pointer in the desired
direction is null Replace the null
pointer a pointer to new IntBTNode( element,
null, null )
- For a balanced tree, the performance of add is
logarithmic
35Some IntTreeBag methods
- public int countOccurrences( int
target ) - Starting at the root, loop as as far as possible
- At the current node, increment count if ( target
data ) - If ( target lt data ) and ( left ! null ), go to
the left child - If ( target gt data ) and ( right ! null ), go to
the right child
- For a balanced tree, the performance of
countOccurrences is logarithmic
36Some IntTreeBag methods
public void addAll( IntTreeBag addend
) Do a preorder or postorder traversal of the
tree of the addend bag Add each node visited to
this
- The traversal of the addend tree is best done
with a recursive (private) helper method - Note an inorder traversal should be avoided
- Recall that an inorder traversal of a BST visits
the nodes in ascending order - The AVL algorithm must be continuously applied to
prevent the new nodes from becoming a linked
list on the right pointers
37Some IntTreeBag methods
public boolean remove( int target )
- This method is implemented by dividing the
problem into three mutually exclusive cases - Target at the root and no left child
- Target not at the root no left child
- Target has a left child
- This is a powerful problem solving technique
- As each case is eliminated, an additional
property is provided to the remaining cases that
may help to solve them
38The remove method
- First search for the target
- If not found, return false
- Then solve the case at hand
root
K
F
M
Target at the root and no left child
root root.getRight()
C
Q
H
D
G
A
Target not at the root no left child if (
cursor parentOfCursor.getLeft() )
parentOfCursor.setLeft( cursor.getRight( )
) else parentOfCursor.setRight(
cursor.getRight( ) )
B
Examples consider nodes A and M
39The remove method
- The final case
- Example consider node F
- Node F is overwritten by D and the old D node is
removed - The BST property remains true
- For a balanced tree, the performance of remove is
logarithmic
Target not at the root and left child exists
cursor.setData( cursor.getLeft(
).getRightmostData() ) cursor.setLeft(
cursor.getLeft( ).removeRightmost() )
root
K
F
M
C
Q
H
D
G
A
B
40IntTreeBag performance examples
- We have seen that add, countOccurrences, and
remove are all O( log(n) ) - In fact, the logarithm has base 2
- Suppose n 1,000,000
- 220 (210)(210) (1024)2 gt 1,000,000
- Thus, log2(n) is no more than 20
- IntTreeBag operations require no more than 20
comparisons - With array and linked list implementations, any
O( n ) method would require up to 1,000,000
comparisons