package edu.princeton.cs.algs4.growingtree.experiments; import edu.princeton.cs.algs4.growingtree.framework.NodeProperties; import edu.princeton.cs.algs4.growingtree.framework.ShadowNode; import edu.princeton.cs.algs4.growingtree.interfaces.IAlgorithmNode; import edu.princeton.cs.algs4.growingtree.interfaces.IDeleteOperator; import edu.princeton.cs.algs4.growingtree.interfaces.IInsertOperator; import edu.princeton.cs.algs4.growingtree.interfaces.ISearchOperator; /** * This wraps around the actual tree, keeping track of the root, and passing * along calls between the API and the tree (e.g. logging, insertion). It should * not be instantiated by the client. * * @author Josh Israel * */ public class ExperimentTree

implements IExperimentLogger

{ private String name; private P p; private IInsertOperator

insertOperator; private ISearchOperator

searchOperator; private IDeleteOperator

deleteOperator; private ShadowNode

root; private IExperimentLogger

logger; /** * * @param name Name of the tree to be created * @param p Instance of the proper NodeProperties subclass * @param inserter The IInsertOperator to be used for this tree * @param searcher The ISearchOperator to be used for this tree * @param deleter The IDeleteOperator to be used for this tree * @param logger The IExperimentLogger to be used for this tree. This * will receive callbacks from the tree when operations occur. */ public ExperimentTree(String name, P p, IInsertOperator

inserter, ISearchOperator

searcher, IDeleteOperator

deleter, IExperimentLogger

logger) { this.name = name; this.p = p; this.insertOperator = inserter; this.searchOperator = searcher; this.deleteOperator = deleter; this.logger = logger; } private ShadowNode

internalSearch(Double key) { ShadowNode

walker = root; while (walker != null) { int cmp = walker.compareTo(key); if (cmp > 0) { walker = walker.getLeft(); } else if (cmp < 0) { walker = walker.getRight(); } else { return walker; } } return null; } private void updateRoot() { root = root.getRoot(); } /** * Insert a node into the tree * @param key Key of the node to be inserted */ public void insert(Double key) { if (root != null) { updateRoot(); int oldSize = root.getNodeProperties().getSize(); ShadowNode

newNode = new ShadowNode

(key,(P) p.makeDefaultProperties(),this); insertOperator.doInsert(root, newNode); updateRoot(); int newSize = root.getNodeProperties().getSize(); assert(oldSize + 1 == newSize); } else { ShadowNode

newRoot = new ShadowNode

(key,(P) p.makeDefaultProperties(),this); root = newRoot; assert (newRoot.getNodeProperties() != null); insertOperator.doInsert(root, null); } assert(root.isBST()); } /** * Perform a search for an element * @param key Key of node to be sought */ public void search(Double key) { updateRoot(); ShadowNode

searchNode = new ShadowNode

(key,(P) p.makeDefaultProperties(), this); searchOperator.doSearch(root, searchNode); } /** * Deletes a node from the tree * @param key Key of node to be deleted */ public void delete(Double key) { // Lots of tricky thinking goes into this to make sure we // don't lose the root updateRoot(); int oldSize = root.getNodeProperties().getSize(); ShadowNode

deleting = internalSearch(key); ShadowNode

rootFinder = root; if (deleting == root) { ShadowNode

l = root.getLeft(); ShadowNode

r= root.getRight(); if (l == null && r == null) { rootFinder = null; } else if (l != null) { rootFinder = l; } else { rootFinder = r; } } if (deleting != null) { assert(deleting.getKey().compareTo(key) == 0); deleteOperator.doDelete(root, deleting); } if (rootFinder == null) { root = null; } else { root = rootFinder.getRoot(); } int newSize = root.getNodeProperties().getSize(); assert(newSize == oldSize - 1); assert(root.isBST()); } /*-------Function below just pass along calls to the logger--*/ public void logInsertion(ShadowNode

n) { assert(n != null); //System.out.println("Logging insertion"); logger.logInsertion(n); } public void logRotation(ShadowNode

n) { //System.out.println("Logging rotation"); logger.logRotation(n); } public void logDeletion(ShadowNode

n) { //System.out.println("Logging deletion"); logger.logDeletion(n); } public void logSearchHit(ShadowNode

n) { //System.out.println("Logging search"); logger.logSearchHit(n); } public void logOther(IAlgorithmNode

n, int event_id) { logger.logOther(n, event_id); } }