Question

In: Computer Science

/** * This class implements a basic Binary Search Tree that supports insert and get operations....

/**
* This class implements a basic Binary Search Tree that supports insert and get operations. In
* addition, the implementation supports traversing the tree in pre-, post-, and in-order. Each node
* of the tree stores a key, value pair.
*
* @param <K> The key type for this tree. Instances of this type are used to look up key, value
* pairs in the tree.
* @param <V> The value type for this tree. An instance of this type is stored in every node, along
* with a key.
*/
public class BST<K extends Comparable<K>, V> {

/**
* Interface for
*
* @param <K> the key type that the traverser works with
* @param <V> the value type that the traverser works with
*/
public interface Traverser<K, V> {

/**
* Method that is called for every visited node.
*
* @param key the key stored in the visited node
* @param value the value stored in the visited node
*/
public void visit(K key, V value);

}

/**
* A tree traverser that prints all values stored in the visited nodes.
*/
private static class IntegerValuePrintTraverser implements Traverser<Integer, Integer> {

/**
* This method is called for every visited node, printing the value stored in the node.
*/
public void visit(Integer key, Integer value) {
System.out.println(value);
}

}

/**
* Nested node class for the tree. Stores a key, value pair and has references to left and right
* child.
*/
private class Node {

public K key = null;
public V value = null;

public Node left = null;
public Node right = null;

/**
* Construct a tree node for a give key, value pair.
*
* @param key The key stored in the node. This determines where in the tree the node will be
* inserted.
* @param value The value stored in the node alongside the key.
*/
public Node(K key, V value) {
this.key = key;
this.value = value;
}

}

// the root node reference for the tree; is null is tree is empty
private Node root = null;
// number of nodes stored in the tree
private int size;

/**
* Insert a new key, value pair into the tree.
*
* @param key
* @param value
* @throws IllegalArgumentException if key is null or if key is already present in tree
*/
public void insert(K key, V value) {
if (key == null) {
throw new IllegalArgumentException("null key not allowed");
}
this.root = this.insertRecursive(this.root, key, value);
this.size++;
}

/**
* Recursive helper method for the public insert method. Recursively traverses the tree and find
* the spot to insert given key.
*
* @param node node that is currently visited
* @param key the key to insert
* @param value the value to insert
* @return return the node that is visits to (re-)attach it to the tree
*/
private Node insertRecursive(Node node, K key, V value) {

if (node == null) {
return new Node(key, value);
} else if (node.key.equals(key)) {
throw new IllegalArgumentException("no duplicate keys allowed");
} else if (node.key.compareTo(key) < 0) {
// new key is larger than current key
node.right = insertRecursive(node.right, key, value);
return node;
} else {
// new key is smaller then current key
node.left = insertRecursive(node.left, key, value);
return node;
}

}

/**
* Retrieve value that is stored for given key in the tree.
*
* @param key the key to look for in the tree
* @throws IllegalArgumentException if key is null
* @return value for key or null if key does not exist in tree
*/
public V get(K key) {
if (key == null) {
throw new IllegalArgumentException("null key not allowed");
}
Node n = getNodeForKey(this.root, key);
if (n == null)
return null;
return n.value;
}

/**
* Recursive helper method for the public insert method. Recursively traverses the tree and find
* the spot to insert given key.
*
* @param node node that is currently visited
* @param key the key to insert
* @param value the value to insert
* @return return the node that is visits to (re-)attach it to the tree
*/
private Node getNodeForKey(Node n, K key) {
if (n == null) {
return null;
} else if (n.key.equals(key)) {
return n;
} else if (n.key.compareTo(key) < 0) {
return getNodeForKey(n.right, key);
} else {
return getNodeForKey(n.left, key);
}
}

/**
* Starts a postorder traversal of the tree.
*
* @param t the traverser to do the traversal with
*/
public void postOrderTraversal(Traverser<K, V> t) {
this.postOrderTraversal(this.root, t);
}

/**
* Helper method that traverses the tree recursively in postorder and calls the traverser for
* every node.
*
* @param n the node that is currently visited
* @param t the traverser to do the traversal with
*/
private void postOrderTraversal(Node n, Traverser<K, V> t) {
if (n != null) {
postOrderTraversal(n.left, t);
postOrderTraversal(n.right, t);
t.visit(n.key, n.value);
}
}

/**
* Starts a preorder traversal of the tree.
*
* @param t the traverser to do the traversal with
*/
public void preOrderTraversal(Traverser<K, V> t) {
this.preOrderTraversal(this.root, t);
}

/**
* Helper method that traverses the tree recursively in preorder and calls the traverser for every
* node.
*
* @param n the node that is currently visited
* @param t the traverser to do the traversal with
*/
private void preOrderTraversal(Node n, Traverser<K, V> t) {
if (n != null) {
t.visit(n.key, n.value);
preOrderTraversal(n.left, t);
preOrderTraversal(n.right, t);
}
}

/**
* Starts an inorder traversal of the tree.
*
* @param t the traverser to do the traversal with
*/
public void inOrderTraversal(Traverser<K, V> t) {
this.inOrderTraversal(this.root, t);
}

/**
* Helper method that traverses the tree recursively in inorder and calls the traverser for every
* node.
*
* @param n the node that is currently visited
* @param t the traverser to do the traversal with
*/
private void inOrderTraversal(Node n, Traverser<K, V> t) {
if (n != null) {
inOrderTraversal(n.left, t);
t.visit(n.key, n.value);
inOrderTraversal(n.right, t);
}
}

  
/**
* Main method with a demo for the tree traverser.
*
* @param args the command line arguments passed when running the program
*/
public static void main(String args[]) {
BST<Integer, Integer> bst = new BST<Integer, Integer>();
// map keys to their squares (values)
bst.insert(7, 49);
bst.insert(2, 4);
bst.insert(10, 100);
bst.insert(1, 1);
bst.insert(8, 64);
System.out.println("pre order traversal:");
bst.preOrderTraversal(new IntegerValuePrintTraverser());
System.out.println("in order traversal:");
// TODO: replace this in order traversal's IntegerValuePrintTraverser object with
// the object of an anonymous class that only prints the keys (not the values)
// in the visited nodes
bst.inOrderTraversal(new IntegerValuePrintTraverser());
System.out.println("post order traversal:");
// TODO: replace this post order traversal's IntegerValuePrintTraverser object with
// the object of a lambda expression that prints both the key and value in the
// visited nodes
bst.postOrderTraversal(new IntegerValuePrintTraverser());
}

}

  1. implement another Traverser that only prints the keys of visited nodes. Implement the traverser using an anonymous class, and replace the new IntegerValuePrintTraverser object passed to the inOrderTraversal method (in BST's main method) with the object created by the anonymous class.
  2. Then implement an additional Traverser that prints both keys and values of visited nodes. Implement the traverser using a lambda expression, and replace the new IntegerValuePrintTraverser object passed to the postOrderTraversal method (in BST's main method) with the object created by the lambda expression.

Solutions

Expert Solution

Java Code with changes done (implemented traverser using lambda expression and anonymous class).

/**
 * This class implements a basic Binary Search Tree that supports insert and get operations. In
 * addition, the implementation supports traversing the tree in pre-, post-, and in-order. Each node
 * of the tree stores a key, value pair.
 *
 * @param <K> The key type for this tree. Instances of this type are used to look up key, value
 *     pairs in the tree.
 * @param <V> The value type for this tree. An instance of this type is stored in every node, along
 *     with a key.
 */
public class BST<K extends Comparable<K>, V> {

  // the root node reference for the tree; is null is tree is empty
  private Node root = null;
  // number of nodes stored in the tree
  private int size;

  /**
   * Main method with a demo for the tree traverser.
   *
   * @param args the command line arguments passed when running the program
   */
  public static void main(String args[]) {
    BST<Integer, Integer> bst = new BST<Integer, Integer>();
    // map keys to their squares (values)
    bst.insert(7, 49);
    bst.insert(2, 4);
    bst.insert(10, 100);
    bst.insert(1, 1);
    bst.insert(8, 64);
    System.out.println("pre order traversal:");
    bst.preOrderTraversal(new IntegerValuePrintTraverser());
    System.out.println("in order traversal:");
    // DONE: replace this in order traversal's IntegerValuePrintTraverser object with
    // the object of an anonymous class that only prints the keys (not the values)
    // in the visited nodes
    bst.inOrderTraversal(
        new Traverser<Integer, Integer>() {
          @Override
          public void visit(Integer key, Integer value) {
            System.out.println(key);
          }
        });
    System.out.println("post order traversal:");
    // DONE: replace this post order traversal's IntegerValuePrintTraverser object with
    // the object of a lambda expression that prints both the key and value in the
    // visited nodes
    bst.postOrderTraversal((key, value) -> System.out.println(key + " -> " + value));
  }

  /**
   * Insert a new key, value pair into the tree.
   *
   * @param key
   * @param value
   * @throws IllegalArgumentException if key is null or if key is already present in tree
   */
  public void insert(K key, V value) {
    if (key == null) {
      throw new IllegalArgumentException("null key not allowed");
    }
    this.root = this.insertRecursive(this.root, key, value);
    this.size++;
  }

  /**
   * Recursive helper method for the public insert method. Recursively traverses the tree and find
   * the spot to insert given key.
   *
   * @param node node that is currently visited
   * @param key the key to insert
   * @param value the value to insert
   * @return return the node that is visits to (re-)attach it to the tree
   */
  private Node insertRecursive(Node node, K key, V value) {

    if (node == null) {
      return new Node(key, value);
    } else if (node.key.equals(key)) {
      throw new IllegalArgumentException("no duplicate keys allowed");
    } else if (node.key.compareTo(key) < 0) {
      // new key is larger than current key
      node.right = insertRecursive(node.right, key, value);
      return node;
    } else {
      // new key is smaller then current key
      node.left = insertRecursive(node.left, key, value);
      return node;
    }
  }

  /**
   * Retrieve value that is stored for given key in the tree.
   *
   * @param key the key to look for in the tree
   * @throws IllegalArgumentException if key is null
   * @return value for key or null if key does not exist in tree
   */
  public V get(K key) {
    if (key == null) {
      throw new IllegalArgumentException("null key not allowed");
    }
    Node n = getNodeForKey(this.root, key);
    if (n == null) return null;
    return n.value;
  }

  /**
   * Recursive helper method for the public insert method. Recursively traverses the tree and find
   * the spot to insert given key.
   *
   * @param node node that is currently visited
   * @param key the key to insert
   * @param value the value to insert
   * @return return the node that is visits to (re-)attach it to the tree
   */
  private Node getNodeForKey(Node n, K key) {
    if (n == null) {
      return null;
    } else if (n.key.equals(key)) {
      return n;
    } else if (n.key.compareTo(key) < 0) {
      return getNodeForKey(n.right, key);
    } else {
      return getNodeForKey(n.left, key);
    }
  }

  /**
   * Starts a postorder traversal of the tree.
   *
   * @param t the traverser to do the traversal with
   */
  public void postOrderTraversal(Traverser<K, V> t) {
    this.postOrderTraversal(this.root, t);
  }

  /**
   * Helper method that traverses the tree recursively in postorder and calls the traverser for
   * every node.
   *
   * @param n the node that is currently visited
   * @param t the traverser to do the traversal with
   */
  private void postOrderTraversal(Node n, Traverser<K, V> t) {
    if (n != null) {
      postOrderTraversal(n.left, t);
      postOrderTraversal(n.right, t);
      t.visit(n.key, n.value);
    }
  }

  /**
   * Starts a preorder traversal of the tree.
   *
   * @param t the traverser to do the traversal with
   */
  public void preOrderTraversal(Traverser<K, V> t) {
    this.preOrderTraversal(this.root, t);
  }

  /**
   * Helper method that traverses the tree recursively in preorder and calls the traverser for every
   * node.
   *
   * @param n the node that is currently visited
   * @param t the traverser to do the traversal with
   */
  private void preOrderTraversal(Node n, Traverser<K, V> t) {
    if (n != null) {
      t.visit(n.key, n.value);
      preOrderTraversal(n.left, t);
      preOrderTraversal(n.right, t);
    }
  }

  /**
   * Starts an inorder traversal of the tree.
   *
   * @param t the traverser to do the traversal with
   */
  public void inOrderTraversal(Traverser<K, V> t) {
    this.inOrderTraversal(this.root, t);
  }

  /**
   * Helper method that traverses the tree recursively in inorder and calls the traverser for every
   * node.
   *
   * @param n the node that is currently visited
   * @param t the traverser to do the traversal with
   */
  private void inOrderTraversal(Node n, Traverser<K, V> t) {
    if (n != null) {
      inOrderTraversal(n.left, t);
      t.visit(n.key, n.value);
      inOrderTraversal(n.right, t);
    }
  }

  /**
   * Interface for
   *
   * @param <K> the key type that the traverser works with
   * @param <V> the value type that the traverser works with
   */
  public interface Traverser<K, V> {

    /**
     * Method that is called for every visited node.
     *
     * @param key the key stored in the visited node
     * @param value the value stored in the visited node
     */
    public void visit(K key, V value);
  }

  /** A tree traverser that prints all values stored in the visited nodes. */
  private static class IntegerValuePrintTraverser implements Traverser<Integer, Integer> {

    /** This method is called for every visited node, printing the value stored in the node. */
    public void visit(Integer key, Integer value) {
      System.out.println(value);
    }
  }

  /**
   * Nested node class for the tree. Stores a key, value pair and has references to left and right
   * child.
   */
  private class Node {

    public K key = null;
    public V value = null;

    public Node left = null;
    public Node right = null;

    /**
     * Construct a tree node for a give key, value pair.
     *
     * @param key The key stored in the node. This determines where in the tree the node will be
     *     inserted.
     * @param value The value stored in the node alongside the key.
     */
    public Node(K key, V value) {
      this.key = key;
      this.value = value;
    }
  }
}

Output:

Code screenshot (only part where changes done):

Please like this answer if you find this helpful.

If you need any help in this question feel free to add a comment.


Related Solutions

Lab 5: Binary Search Tree Implement operations for a Binary Search Tree class starting from the...
Lab 5: Binary Search Tree Implement operations for a Binary Search Tree class starting from the template provided under the PolyLearn assignment, using the class TreeNode that is also provided. You may (should) implement helper methods that make your code easier to write, read, and understand. You will also need to write test cases of your own as you develop the methods. You may use iterative and/or recursive functions in your implementation. The following starter files are available . •...
In MobaXterm, with the use of the binary search tree. Implement four operations of insert, in-order...
In MobaXterm, with the use of the binary search tree. Implement four operations of insert, in-order traversal, preorder traversal, and find. Please separate the code in the four parts and explain in detail what is happening. Also, if you can please basic C language. If not, then I understand. Thank you for your time. The test cases are 'm', 'd', 'g', 'r', 'p', 'b', and 'x'. Output: Enter choice (lower case is also acceptable) --- (I)nsert, (F)ind, (Q)uit: i Enter...
Beginning with an empty binary search tree, what binary search tree is formed when you insert...
Beginning with an empty binary search tree, what binary search tree is formed when you insert the following values in the given order – consider there alphabetical position for comparison. a. W, T, N, J, E, B, A b. W, T, N, A, B, E, J c. A, B, W, J, N, T, E d. B, T, E, A, N, W, J Alphabetical positions: A-1, B-2, E-5, J-10, N-14,T-20,W-23
Prerequisite Knowledge Understand binary search tree structure Understand binary search tree operations Understand binary search tree...
Prerequisite Knowledge Understand binary search tree structure Understand binary search tree operations Understand binary search tree worst case and best case time. Learning Outcomes Describe AVL tree structure Trace and implement AVL tree operations Explain and prove AVL tree performance
You are given a reference to the root node of a binary search tree, that implements...
You are given a reference to the root node of a binary search tree, that implements a dictionary data structure. Please print all the elements in depths 500 through 510, all in sorted order. A node in a binary search tree is at depth x, if it takes x hops to get from the root. So the root is at depth 0, the children of the root are at depth 1, and so on. The class TreeNode defines a single...
You are given a reference to the root node of a binary search tree, that implements...
You are given a reference to the root node of a binary search tree, that implements a dictionary data structure. Please print all the elements in depths 500 through 510, all in sorted order. A node in a binary search tree is at depth x, if it takes x hops to get from the root. So the root is at depth 0, the children of the root are at depth 1, and so on. The class TreeNode defines a single...
​Define a tree. Distinguish between a tree and a binary tree. Distinguish between a binary tree and a binary search tree.
Define a tree. Distinguish between a tree and a binary tree. Distinguish between a binary tree and a binary search tree.
c++ Binary Search Tree: find parent of a node please insert comment to explain what the...
c++ Binary Search Tree: find parent of a node please insert comment to explain what the code do. Use struct Node{ int data; Node* left; Node* right};
Show how to augment the ordinary Binary Search Tree (BST) data structure so that it supports...
Show how to augment the ordinary Binary Search Tree (BST) data structure so that it supports an efficient procedure which, on input (x, k) where x is the root of a BST and k an integer, output the k-th smallest number store in the BST. Let n denote the total number of elements stored in the BST, what is the running time of your efficient procedure? How does your modification of the BST data structure affect the performance of other...
Write the class Complex that supports the basic complex number operations. Such operations are addition (+),...
Write the class Complex that supports the basic complex number operations. Such operations are addition (+), subtraction (-) and multiplication (*) of complex numbers, and multiplication (*) of a complex by a scalar (float or int). All methods must return (not print) the result. Class also supports the rich comparison for equality (= =) - Check the doctest for object behavior examples. - You must use the special methods for those 4 operators in order to override their behavior -...
ADVERTISEMENT
ADVERTISEMENT
ADVERTISEMENT