|
CS 535 Object-Oriented Programming & Design Spring Semester, 1999 Distribute System Intelligence: A Tree Example |
|
|---|---|---|
|
© 1999, All Rights Reserved, SDSU & Roger Whitney San Diego State University -- This page last updated 27-Apr-99 |
Distribute System Intelligence
A Tree Example
Problem:
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;
}
}
package sdsu.trees;
import java.util.*;
public class SmartTree
{
protected DumbNode root = null;
// Methods shown later
}
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;
}
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;
}
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;
}
}
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) ) )
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;
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();
}
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 ) );
}
}
Solution
2 DumbTree,
BSTNode
1) Let the nodes do some work
2) Add some nil leaves to eliminate some cases
Class
StructureInheritance
Runtime
Structure

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();
}
}
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
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() + ")";
}
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 );
}
}
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 "";
}
}
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;
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 );
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;
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 );
Comparison
| Metric | SmartTree | DumbTree |
| LOC | 60 | 36 |
| Number of classes | 3 | 4 |
| Number of methods | 6[1] | 18[2] |
| LOC/method | 10 | 2 |
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; }
Issues: Performance
Have you lost your mind?
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 -> | 400 | 800 | 1600 |
| SmartTree create | 264 | 1064 | 4342 |
| DumbTree create | 314 | 1290 | 5681 |
| SmartTree find all | 261 | 1049 | 4197 |
| DumbTree find all | 272 | 1193 | 5370 |
More Timing Results
| N -> | 400 | 800 | 1600 |
| SmartTree create | 264 | 1064 | 4342 |
| DumbTree create | 314 | 1290 | 5681 |
| DumbAVLTree create | 46 | 94 | 196 |
| Hashtable create | 42 | 82 | 165 |
| Opt. Hashtable create | 25 | 57 | 102 |
| SmartTree find all | 261 | 1049 | 4197 |
| DumbTree find all | 272 | 1193 | 5370 |
| DumbAVLTree find all | 11 | 23 | 50 |
| Hashtable find all | 30 | 61 | 127 |
| Opt. Hashtable find all | 14 | 27 | 54 |
[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