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
Routine to Compute Height

  • 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.
Inorder Traversal using Stack Inorder Algorithm init: push root onto the stack with state 0

  • 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):

    >Sequence: A - B - C - D - E - F - G - H - I
  • 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.