Trees 2 CSC 172 SPRING 2004 LECTURE 15
Why Structural Induction? Q: Why do I want you to draw the pictures? A: We know you can do the algebra. As you move on, the difficult part of the proofs is “setting up” the proof, from some situation. Sure, if someone sets it up for you, it’s just an “exercise” to solve. The real value is in being able to reason about a situation so as to set up a proof.
Process Real world Formal phenomena Rigorous Representation Knowledge or artifact Formal Representation “set up” of proof Rigorous Knowledge Formal techniques: induction, algebra Informal reasoning abstraction analysis
Kraft’s Inequality Suppose that a binary tree has leaves {l1,l2,..lM} at depths {d1,d2,...,dM}, respectively. Prove:
How do you set this up?
How do you set this up? Basis: In a tree with zero nodes, the sum is zero In a tree with one node One leaf, depth 0
T1 ∑1<=1 T2 ∑2<=1 Same number of total leaves, all depths increase by 1 So, in new Tree ∑1<=1/2 && ∑2<=1/2
A tree viewed recursively
Size of a tree Recursive view ST = SL + SR + 1
Size of a Tree public static int size (BinaryNode t) { if (t == null) return 0 ; else return 1 + size(t.left) + size(t.right); }
Height of a tree Recursive view of height calculation HT = Max(HL,HR) + 1;
Height of a Tree public static int height (BinaryNode t) { if (t == null) return -1 ; else return 1 + Math.max(height(t.left)) ,(height(t.right)); }
Tree Traversal Preorder Postorder Inorder
Preorder public void printPreOrder() { System.out.println(element); if (left != null) left.printPreOrder(); if (right != null) right.printPreOrder(); }
Postorder public void printPostOrder() { if (left != null) left.printPostOrder(); if (right != null) right.printPostOrder(); System.out.println(element); }
Inorder public void printInOrder() { if (left != null) left.printInOrder(); System.out.println(element); if (right != null) right.printInOrder(); }
Tree Iterators Stack use to implement recursion Linear Good demonstration of class hierarchy in design
TreeIterator class abstract class TreeIterator { public TreeIterator( BinaryTree theTree ) { t = theTree; current = null; } abstract public void first( ); final public boolean isValid( ) { return current != null;} final public Object retrieve( ) { if( current == null ) throw new NoSuchElementException( "TreeIterator retrieve" ); return current.getElement( ); } abstract public void advance( ); protected BinaryTree t; // Tree protected BinaryNode current; // Current position
Stacks for Recursion We have seen recursion We know we can use recursion But how do the virtual machines actually *do* recursion We can use a stack to implement recursion Lets consider the PostOrder traversal implementing recursion in the iterator with a stack
The Algorithm The top of the stack is the “current” node We can be in one of 3 states while at the current node About to recurse to the left About to recurse to the right About to process the current node So, we put each node on the stack 3 times The 3rd time we pop, we process
Stack states during postorder
Implementation class PostOrder extends TreeIterator { public PostOrder( BinaryTree theTree ) { super( theTree ); s = new ArrayStack( ); s.push( new StNode( t.getRoot( ) ) ); } public void first( ) { s.makeEmpty( ); if( t.getRoot( ) != null ) { advance( );
Implementation protected static class StNode { BinaryNode node; int timesPopped; StNode( BinaryNode n ){ node = n; timesPopped = 0; } /** An internal stack if visited nodes. */ protected Stack s;
Implementation: advance public void advance( ) { if( s.isEmpty( ) ){ // check for null if( current == null ) throw new NoSuchElementException( "PostOrder Advance" ); current = null; return; }
Implementation StNode cnode; for( ; ; ) { cnode = ( StNode ) s.topAndPop( ); if( ++cnode.timesPopped == 3 ) { current = cnode.node; return; } s.push( cnode ); if( cnode.timesPopped == 1 ) { if( cnode.node.getLeft( ) != null ) s.push( new StNode( cnode.node.getLeft( ) ) ); } else { // cnode.timesPopped == 2 if( cnode.node.getRight( ) != null ) s.push( new StNode( cnode.node.getRight( ) ) );