SDSU CS 535 Object-Oriented Programming & Design
Spring Semester, 1999
Distribute System Intelligence: A Tree Example
Previous    Lecture Notes Index    Next    
© 1999, All Rights Reserved, SDSU & Roger Whitney
San Diego State University -- This page last updated 27-Apr-99

Contents of Doc 18, Distribute System Intelligence: A Tree Example


References

Roger Whitney’s Lecture notes

Doc 18, Distribute System Intelligence: A Tree Example Slide # 2

Distribute System Intelligence

A Tree Example

Problem:

Implement a binary search tree with operations:
put( int key, Object value )
Puts the specified value into the tree, using the specified key.
get( int key )
Gets the object associated with the specified key in the tree.
toString()
Returns a string representation of the tree
( leftSubtree root rightSubtree )


((3)5((6)8(9)))

Doc 18, Distribute System Intelligence: A Tree Example Slide # 3

Solution 1 SmartTree, DumbNode


DumbNode

class DumbNode 
   {
   protected DumbNode left = null;
   protected DumbNode right = null;
   
   protected int key;
   protected Object value;
   
   public DumbNode( int key, Object value )
      {
      this.key = key;
      this.value = value;
      }
   }

SmartTree Fields
package sdsu.trees;
import java.util.*;
public class SmartTree
   {
   protected DumbNode root = null;
   // Methods shown later
   }

Doc 18, Distribute System Intelligence: A Tree Example Slide # 4
SmartTree MethodsHelper Function

/**
 * If keyToFind is in the tree rooted at startNode, then return node 
 * containing keyToFind.
 * Otherwise return the node that would be parent of a node containing 
 * keyToFind.
 */
protected DumbNode getNode( int keyToFind, DumbNode startNode )
   {
   DumbNode current = startNode;
   DumbNode parent = null;
   DumbNode nextNode = null;
   while ( current != null )
      {
      if ( keyToFind < current.key )
         nextNode = current.left;
      else if (keyToFind > current.key  )
         nextNode = current.right;
      else 
         return current;
      parent = current;
      current = nextNode;
      }
   
   // Key not found,
   return parent;
   }


Doc 18, Distribute System Intelligence: A Tree Example Slide # 5
SmartTree Methodsget

/**
 * Gets the object associated with the specified key in the tree. 
 * If key is not in tree return null
 */
public Object get( int key )
   {
   if ( root == null )
      return null;
   
   DumbNode foundNode = getNode( key, root );
   
   if ( foundNode.key  ==  key )
      return foundNode.value;
   else
      return null;
   }


Doc 18, Distribute System Intelligence: A Tree Example Slide # 6
SmartTree Methodsput

/**
 * Puts the specified element into the tree, using the specified key.
 */
public Object put( int key, Object value )
   {
   if ( root == null )
      {
      root = new DumbNode( key, value );
      return null;
      }
   
   DumbNode foundNode = getNode( key, root );
   
   if ( foundNode.key  ==  key )
      {
      // Replace existing value
      Object oldValue = foundNode.value;
      foundNode.value = value;
      return oldValue;
      }
   else   //Key not in tree, add new node
      {
      if ( key > foundNode.key )
         foundNode.right = new DumbNode( key, value );
      else
         foundNode.left = new DumbNode( key, value );
      
      return null;
      }
   }


Doc 18, Distribute System Intelligence: A Tree Example Slide # 7
SmartTree MethodsPreorder Traversal

1) Print "(" then Visit left subtree
2) Print node
3) Visit right subtree, then print ")"


Applying rule we get:

(   left subtree   5   right subtree   )
(   (3)   5   (   left subtree   8   right subtree    )   )
(   (3)   5   (    (6)   8   (9)   )   )

Doc 18, Distribute System Intelligence: A Tree Example Slide # 8
SmartTree MethodstoString() Helper Class

Need to store path of nodes visited on a stack with which visit we are on: first, second or third


public class TraversalInfo
   {
   public DumbNode node;
   public int visitNumber;
   public TraversalInfo( DumbNode nodeTraversed, int visitNumber )
      {
      node = nodeTraversed;
      this.visitNumber = visitNumber;
      }
   }
Constants for toString()

private final static int FIRST = 1;
private final static int SECOND = 2;
private final static int THIRD = 3;

Doc 18, Distribute System Intelligence: A Tree Example Slide # 9
SmartTree MethodstoString(): Simple Algorithm

public String toString()
   {
   StringBuffer treeString = new StringBuffer();
   TraversalInfo currentLocation;
   
   Stack visited = new Stack();
   visited.push( new TraversalInfo( root, FIRST ) );
   
   while ( visited.empty() != true )
      {
      currentLocation = (TraversalInfo) visited.pop();
      
      switch ( currentLocation.visitNumber )
         {
         case FIRST:
            treeString.append( "(" );
            firstVisit( visited, currentLocation );
            break;
            
         case SECOND:
            treeString.append( currentLocation.node.key );
            secondVisit( visited, currentLocation );
            break;
            
         case THIRD:
            treeString.append( ")" );
            break;
         }
      }
   return treeString.toString();
   }

Doc 18, Distribute System Intelligence: A Tree Example Slide # 10
SmartTree MethodstoString(): continued

protected void firstVisit( Stack visited, TraversalInfo currentLocation )
   {
   DumbNode nextnode;
   currentLocation.visitNumber = SECOND;
   visited.push( currentLocation );
   if ( currentLocation.node.left != null )
      {
      nextnode = currentLocation.node.left;
      visited.push( new TraversalInfo( nextnode, FIRST )  );
      }
   }
protected void secondVisit( Stack visited, 
                        TraversalInfo currentLocation )
   {
   DumbNode nextnode;
   currentLocation.visitNumber = THIRD;
   visited.push( currentLocation );      
   if ( currentLocation.node.right != null )
      {
      nextnode = currentLocation.node.right;
      visited.push( new TraversalInfo( nextnode, FIRST )  );
      }
   }

Doc 18, Distribute System Intelligence: A Tree Example Slide # 11

Solution 2 DumbTree, BSTNode


1) Let the nodes do some work
2) Add some nil leaves to eliminate some cases


Class StructureInheritance


Runtime Structure


Doc 18, Distribute System Intelligence: A Tree Example Slide # 12

DumbTree


package sdsu.trees;
public class DumbTree
   {
   protected TreeNode root = null;
   
   public Object get( int key )
      {
      if ( root == null )
         return null;
      
      return root.getNode( key ).value();
      }
   public Object put( int key, Object value )
      {
      if ( root == null )
         {
         root = new BSTNode( key, value );
         return null;
         }
      
      return root.getNode( key ).put( key, value );
      }
   
   public String toString()
      {
      return root.toString();
      }
   }

Doc 18, Distribute System Intelligence: A Tree Example Slide # 13

TreeNode

abstract class TreeNode
   {
   /**
    * Puts the specified key & value in this node
    */
   abstract public Object put( int key, Object value );
   /**
    * Return the value of the TreeNode
    */
   abstract public Object value();
   /**
    * If keyToFind is in the subtree rooted at this node, then return 
    * node containing keyToFind.
    * Otherwise return the NilLeaf that should contain keyToFind  
    */
   abstract public TreeNode getNode( int key );
   /**
    * Return an ascii representation of tree rooted at this node
    */
   abstract public String toString();
   }
Comments

There is no common code or methods between BSTNode and NilLeaf

TreeNode could be either an interface or an abstract class

Doc 18, Distribute System Intelligence: A Tree Example Slide # 14

BSTNode


class BSTNode extends TreeNode
   {
   protected TreeNode left;
   protected TreeNode right;
   
   protected int key;
   protected Object value;
   
   public BSTNode( int key, Object value )
      {
      this.key = key;
      this.value = value;
      left = new NilLeaf( this );
      right = new NilLeaf( this );
      }
   
   /**
    * Return the value of the TreeNode
    */
   public Object value()
      {
      return value;
      }
      
   /**
    * Return an ascii representation of tree rooted at this node
    */
   public String toString()
      {
      return "(" + left.toString()  + key +  right.toString() + ")";
      }

Doc 18, Distribute System Intelligence: A Tree Example Slide # 15
BSTNode Continued

   public Object put( int keyToAdd, Object valueToAdd )
      {
      Object oldValue = value;
      value = valueToAdd;
      return oldValue;
      }
   
   /**
    * If keyToFind is in the subtree rooted at this node, then return 
    * node containing keyToFind.
    * Otherwise return the NilLeaf that should contain keyToFind  
    */
   public TreeNode getNode( int keyToFind )
      {
      if ( keyToFind < key )
         return left.getNode( keyToFind );
      else if ( keyToFind > key )
         return right.getNode( keyToFind );
      else
         return this;
      }
   /**
    * Puts indicated key and value in proper child of this node
    */
   protected void putAsChild( int keyToAdd, Object valueToAdd )
      {
      if ( keyToAdd < key )
         left = new BSTNode( keyToAdd, valueToAdd );
      else if ( keyToAdd > key )
         right = new BSTNode( keyToAdd, valueToAdd );
      }
   }

Doc 18, Distribute System Intelligence: A Tree Example Slide # 16

NilLeaf


class NilLeaf extends TreeNode
   {
   protected BSTNode parent;
   
   public NilLeaf( BSTNode parent )
      {
      this.parent = parent;
      }
   public Object put( int key, Object value )
      {
      parent.putAsChild( key, value );
      return null;
      }
      
   public Object value()
      {
      return null;
      }
   
   public TreeNode getNode( int key )
      {
      return this;
      }
   public String toString()
      {
      return "";
      }
   }

Doc 18, Distribute System Intelligence: A Tree Example Slide # 17

How Does this Work?


DumbTree example = new DumbTree();
example.put( 5, null );
example.put( 3, null );
example.put( 8, null );
// Now add a 1

example.put( 1, null );
// In DumbTree's put( 1, null ) method does:
   return root.getNode( 1 ).put( 1, null );

// in BSTNode with key 5 method getNode( 1 ) does:
      if ( 1 < 5 )
         return left.getNode( 1 );
      else if ( 1 > 5 )
         return right.getNode( 1 );
      else
         return this;


Doc 18, Distribute System Intelligence: A Tree Example Slide # 18
Example Continued


// in BSTNode with key 3 method getNode( 1 ) does:
      if ( 1 < 3 )
         return left.getNode( 1 );
      else if ( 1 > 3 )


// in NilNode method getNode( 1 ) does:

      return this;


// in BSTNode with key 3 method getNode( 1 ) does:
      if ( 1 < 3 )
         return left.getNode( 1 );

Doc 18, Distribute System Intelligence: A Tree Example Slide # 19
Example Continued


// in BSTNode with key 5 method getNode( 1 ) does:
      if ( 1 < 5 )
         return left.getNode( 1 );


// In DumbTree's put( 1, null ) method does:
   return root.getNode( 1 ).put( 1, null );

// in NilNode method put( 1, null ) does:
      parent.putAsChild( 1, null );
      return null;

Doc 18, Distribute System Intelligence: A Tree Example Slide # 20
Example Continued


// in BSTNode with key 3 method putAsChild( 1, null ) does:
      if ( 1 < 3 )
         left = new BSTNode( 1, null );
      else if ( 1 > 3 )

// in NilNode method put( 1, null ) does:
      parent.putAsChild( 1, null );
      return null;


// In DumbTree's put( 1, null ) method does:
   return root.getNode( 1 ).put( 1, null );

Doc 18, Distribute System Intelligence: A Tree Example Slide # 21

Comparison



MetricSmartTreeDumbTree
LOC6036
Number of classes34
Number of methods6[1]18[2]
LOC/method102


SmartTree is centralized

DumbTree distributes the logic in the tree structure

Doc 18, Distribute System Intelligence: A Tree Example Slide # 22
Issue

Avoid Case (and if) Statements


Implementation that avoids if statements by sending a message to an object

NilLeaf returns a null string;

   public String toString()
      {
      return "(" + left.toString()  + key +  right.toString() + ")";
      }


Implementation that uses if statements

   public String toString()
      {
      String treeRepresentation;
      treeRepresentation = "(";
      if ( left != null )
         treeRepresentation = treeRepresentation + left.toString();
      treeRepresentation = treeRepresentation + left.toString();
      if ( right != null )
         treeRepresentation = treeRepresentation + right.toString();
      treeRepresentation = treeRepresentation + ")";
      return treeRepresentation;
      }

Doc 18, Distribute System Intelligence: A Tree Example Slide # 23

Issues: Performance


Have you lost your mind?

NilLeaf doubles the space requirement
DumbTree's recursive like search requires considerable stack space
DumbTree's recursive like search is slower than SmartTree's iterative search


NilLeaf doubles the space requirement

True, but one only needs NilLeaf per tree


Recursion requires considerable stack space

This is true of any recursive solution

Simulations indicate Metroworks Java implementation runs out of stack space after about 8,200 recursive calls to the same method

See AVLTree

Doc 18, Distribute System Intelligence: A Tree Example Slide # 24
DumbTree is slower than SmartTreePerformance Test

Insert ints from 1 to N into each tree

Look up each int once

Times are measured on a PowerMac 7100/80

Times are in milliseconds

Timing Results

N ->4008001600
SmartTree create26410644342
DumbTree create31412905681
SmartTree find all26110494197
DumbTree find all27211935370


Doc 18, Distribute System Intelligence: A Tree Example Slide # 25
More Timing Results


N ->4008001600
SmartTree create26410644342
DumbTree create31412905681
DumbAVLTree create4694196
Hashtable create4282165
Opt. Hashtable create2557102
SmartTree find all26110494197
DumbTree find all27211935370
DumbAVLTree find all112350
Hashtable find all3061127
Opt. Hashtable find all142754


SmartTree is a binary search tree using iterative search

DumbTree is a binary search tree using recursive search

DumbAVLTree is an AVL tree using recursive search

Hashtable is Java's standard Hashtable with methods synchronized

Opt. Hashtable is Java's standard Hashtable with synchronization removed

Doc 18, Distribute System Intelligence: A Tree Example Slide # 26
[1]Originally firstVisit and second visit methods did not exist. They were added just to make each method fit on one slide. Hence I did not count them as methods for this comparison.
[2]This includes the abstract class

Copyright ©, All rights reserved.
1999 SDSU & Roger Whitney, 5500 Campanile Drive, San Diego, CA 92182-7700 USA.
OpenContent license defines the copyright on this document.

Previous    visitors since 27-Apr-99    Next