Recursive View: a binary tree is either
Outline
- Tree Data Structure
- – Examples – Terminology & Definition
- Binary Tree • Tree Traversal • Tree Iterators
Trees: Some Examples Trees: Some Examples
- – Table of contents of a book
- A tree represents a hierarchy, for example:
- – Organizational structure of a company
Trees: Terminology Trees: Some Examples
is the
A root node
is the of D and E
B parent
- – File system (Unix, Windows, Internet)
C is the sibling of B D and E are the children of B
D, E, F, G, I are external nodes , or leaves
A, B, C, H are internal nodes
The depth , level , or path length of E is 2 The height of the tree is 3 The degree of node B is 2
Trees: Viewed Recursively Binary Trees
Binary tree: tree with all internal nodes of degree 2 Recursive View: a binary tree is either empty an internal node (the root ) and two binary trees (left subtree and right subtree)
A sub-tree is also a tree!!
- If we restrict that each parent can have two and only two children, then:
- Arithmetic expression
- – |external nodes| = |internal nodes| + 1
- – |nodes at level i| ≤ ≤ ≤
- – |external nodes| ≤ ≤ ≤
- – height ≥ ≥ ≥
- – height ≥
- – height ≤
- Preorder Traversal
Algorithm postOrder(v) for each child w of v do recursively perform postOrder(w) “visit” node v
Traversing Trees: Postorder Postorder Traversal
“visit” node v for each child w of v do recursively perform preOrder(w)
Algorithm preOrder(v)
Traversing Trees: Preorder
≤ ≤ ≤ |internal nodes| = (|nodes| - 1)/2
|nodes| - 1
2
≥ ≥ ≥ log
|external nodes|
2
≥ log
(height)
2
≤
i
2
≤
Binary Trees: Properties
Binary Trees: An Example
Example: du (disk usage) command in Unix
- Example: reading a document from beginning to end
- Algorithm evaluateExpression (v)
- Inorder traversal of a
- Example: printing an arithmetic expression
- – print “(“ before traversing the left subtree
- – print “)” after traversing the right subtree
T
R
L
H
R
H
L
H
R
L
= max (H
Think Recursively
- Computing the height of a tree is complex without recursion.
- The height of a tree is one more than the maximum of the heights of the subtrees.
The tree stores a reference to the root node, which is the starting point. public class BinaryTree <T> { private BinaryNode<T> root; // Root node public BinaryTree() // Default constructor { root = null; } }
}
T element; /* Item stored in node */ BinaryNode<T> left; BinaryNode<T> right;
class BinaryNode <T> {
The BinaryNode in Java
binary tree Algorithm inOrder (v) recursively perform inOrder (leftChild(v)) “visit” node v recursively perform inOrder (rightChild(v))
Traversing Trees: Inorder
if v is an external node return the variable stored at v else let o be the operator stored at v x ← evaluateExpression (leftChild(v)) y ← evaluateExpression (rightChild(v)) return x o y
Traversing Trees
A tree is a collection of nodes:
- – H
- 1, H
- 1)
- 1
- 1 H
- Handle base case (empty tree) • Use previous observation for recursive case.
public static int height (BinaryNode t) { if (t == null) return 0; else return 1 + max(height (t.left), height (t.right)); } Running Time
- This strategy is a postorder traversal: information for a tree node is computed after the information for its children is computed.
- The running time of tree traversal is N times the cost of processing each node.
- Thus, the running time is linear because we do constant work for each node in the tree.
Print Preorder
Print Postorder
class BinaryNode { void printPreOrder( )
{ System.out.println( element ); // Node if( left != null ) left.printPreOrder( ); // Left if( right != null ) right.printPreOrder( ); // Right
} } class BinaryTree { public void printPreOrder( )
{ if( root != null ) root.printPreOrder( );
} }
class BinaryNode { void printPostOrder( )
{ if( left != null ) left.printPostOrder( ); // Left if( right != null ) right.printPostOrder( ); // Right
System.out.println( element ); // Node }
} class BinaryTree { public void printPostOrder( )
{ if( root != null ) root.printPostOrder( );
} }
Print Inorder
class BinaryNode { void printInOrder( )
{ if( left != null ) left.printInOrder( ); // Left
System.out.println( element ); // Node if( right != null ) right.printInOrder( ); // Right
} } class BinaryTree { public void printInOrder( )
{ if( root != null ) root.printInOrder( );
} }
Traversing Tree Exercise • A tree contains Integer objects.
Tree Iterator Class Can we implement traversal non-recursively ? Recursion is implemented by using a stack.
- – Find the maximum value
- – Find the total value
We can traverse non-recursively by maintaining the stack ourselves ( emulate stack of activation records ).
Is a non-recursive approach faster than recursive approach? Possibly:we can place only the essentials, while the Postorder Traversal using Stack Postorder Algorithm init: push root onto stack with state 0
Use stack to store the current state (nodes we advance: have traversed but not yet completed) while (true)
Similar to PC (program counter) in the activation node X = pop from the stack switch (state X): record
case 0:
We “pop” each node three times, when: push node X with state 1
push left child of X (if it exists) with state 0
0. about to make a recursive call to left subtree
case 1: push node X with state 2
1. about to make a recursive call to right subtree
push right child of X (if it exists) with state 0 case 2:
2. about to process the current node itself
node X
visit/process Postorder Traversal: Stack States
Exercise
- Create a non-recursive algorithm for inorder traversal using stack.
- Create a non-recursive algorithm for preorder traversal using stack.
- What are the states for inorder traversal?
advance: 0. about to make a recursive call to left subtree while (true)
1. about to process the current node node X = pop from the stack switch (state X):
2. about to make a recursive call to right subtree
case 0: push node X with state 1 push left child of X (if it exists) with state 0 case 1: push node X with state 2 node X
visit/process
case 2: push right child of X (if it exists) with state 0
Inorder Algorithm (improved) Preorder Traversal using Stack
- init: push root onto the stack with state 0
- What are the states for preorder traver
- advance (optimize):
0. about to process the current node
- – while (true)
1. about to make a recursive call to left subtree
- node X = pop from the stack
2. about to make a recursive call to right subtree
- switch (state X):
- – case 0:
» push node X with state 1 » push left child of X (if it exists) with state 0
- – case 1:
» visit/process node X
» push right child of X (if it exists) with state 0 Preorder Algorithm Preorder Algorithm (improved) init: push root onto the stack with state 0
- init: push root onto the stack
advance:
- advance (optimized):
while (true)
- – while (true)
node X = pop from the stack
- node X = pop from the stack
switch (state X):
case 0:
- visit/process node X
push node X with state 1
- push right child of X (if it exists)
the node X
visit/process
case 1:
- push left child of X (if it exists)
push node X with state 2 push left child of X (if it exists) with state 0 case 2: push right child of X (if it exists) with state 0
Level-Order Traversal Level-Order Traversal: Idea
- Visit root followed by its children from left to • Using a queue instead of a stack right and followed by their children. So we go • Algorithm (similar to pre-order) down the tree level by level.
- – init: enqueue the root into the queue
- – while(true):
- node X = dequeue from the queue
- visit/process node X;
- enqueue left child of node X (if it exists);
- enqueue right child of node X (if it exists);
Binary Tree: Properties Summary
Tree, Binary Tree
Maximum number of nodes in a binary tree of height k is
k+1 In order to process the elements of a tree, we consider accessing the 2 -1. elements in certain order
A full binary tree with height k is a binary tree which has
Tree traversal is a tree operation that involves "visiting” (or" processing") all k+1 2 - 1 nodes. the nodes in a tree.
A complete binary tree with height k is a binary tree which Depth First Search (DFS): has maximum number of nodes possible in levels 0 through
Pre-order : Visit node first, pre-order all its subtrees from leftmost to k -1, and in (k -1)’th level all nodes with children are rightmost. selected from left to right.
Inorder : Inorder the node in left subtree and then visit the root following by inorder traversal of all its right subtrees.
Complete binary tree with n nodes can be shown by using Post-order : Post-order the node in left subtree and then post-order the an array, then for any node with index i, we have: right subtrees followed by visit to the node.
Parent (i) is at i/2 if i ≠1; for i =1, we have no parent.
Breadth First Search (BFS): Left-child (i ) is at 2i if 2i ≤ n. (else no left-child)
Level-order : Visit root followed by its children from left to right and Right-child (i ) is at 2i+1 if 2i +1 ≤ n (else no right-child) followed by their children. So we go down the tree level by level.