package cse1030; /** * A binary search tree class. * *

* A binary search tree is a binary tree where values are stored in the tree * according to three rules: * *

    *
  1. values in the left subtree are less than values in the root node *
  2. values in the right subtree are greater than or equal to values in the * root node *
  3. rules 1 and 2 apply recursively to every subtree *
* * @author CSE1030Z * * @param */ public class BinarySearchTree> { /** * A class that represents nodes in the binary search tree. Each * node stores a data element, and has a left and right child node. * This inner class is public for testing purposes only; normally, * Node would be a private inner class. * * @author CSE1030Z * * @param */ public static class Node { private E data; private Node left; private Node right; /** * Create a node with the given data element. The left * and right child nodes are set to null. * * @param data the element to store */ public Node(E data) { this.data = data; this.left = null; this.right = null; } /** * Get the left child node; for testing purposes only. * * @return the left child node */ public Node left() { return this.left; } /** * Get the right child node; for testing purposes only. * * @return the right child node */ public Node right() { return this.right; } /** * Get the data stored in the node; for testing purposes only. * * @return the data stored in the node */ public E data() { return this.data; } } private Node root; /** * Create an empty binary search tree. */ public BinarySearchTree() { this.root = null; } /** * Add an element to the tree. The element is inserted into the tree in a * position that preserves the definition of a binary search tree. * * @param element * the element to add to the tree */ public void add(E element) { if (this.root == null) { this.root = new Node(element); } else { BinarySearchTree.add(element, this.root); } } /** * Add an element to the subtree rooted at subtreeRoot. The * element is inserted into the tree in a position that preserves the * definition of a binary search tree. * * @param element * the element to add to the subtree * @param subtreeRoot * the root of the subtree */ private static > void add(E element, Node subtreeRoot) { if (element.compareTo(subtreeRoot.data) < 0) { if (subtreeRoot.left == null) { subtreeRoot.left = new Node(element); } else { BinarySearchTree.add(element, subtreeRoot.left); } } else { if (subtreeRoot.right == null) { subtreeRoot.right = new Node(element); } else { BinarySearchTree.add(element, subtreeRoot.right); } } } /** * Returns true if the tree contains the given element, * false otherwise. * * @param element * the element to search for * @return true if the tree contains the given element, * false otherwise */ public boolean contains(E element) { return contains(element, this.root); } /** * Returns true if the subtree rooted at subtreeRoot * contains the given element, false otherwise. * * @param element * the element to search for * @param subtreeRoot * the root of the subtree * @return true if the subtree rooted at subtreeRoot * contains the given element, false otherwise */ private static > boolean contains(E element, Node subtreeRoot) { if (subtreeRoot == null) { return false; } if (element.equals(subtreeRoot.data)) { return true; } boolean result; if (element.compareTo(subtreeRoot.data) < 0) { result = contains(element, subtreeRoot.left); } else { result = contains(element, subtreeRoot.right); } return result; } /** * Return a string representation of the tree. * *

* The string is made up of the elements stored in the tree separated * by commas; the entire list of elements is enclosed in braces. The * elements are in ascending sorted order. * * @see java.lang.Object#toString() * * @return a string representation of the tree */ @Override public String toString() { return "{" + toString(this.root) + "}"; } /** * Return a string representation of the subtree rooted at subtreeRoot. * *

* The string is made up of the elements stored in the tree separated * by commas where the elements are in ascending sorted order. * *

* The string is generated using inorder processing of the subtree: * *

    *
  1. the string corresponding to subtreeRoot.left is computed *
  2. the string corresponding to subtreeRoot.data is computed *
  3. the string corresponding to subtreeRoot.right is computed *
* *

* The returned string is the concatenation of the three strings computed by the * inorder processing of the subtree. * * @param subtreeRoot the root of the subtree * @return the string representation of the subtree */ private static > String toString( Node subtreeRoot) { if (subtreeRoot == null) { return ""; } String left = toString(subtreeRoot.left); if (!left.isEmpty()) { left = left + ", "; } String right = toString(subtreeRoot.right); if (!right.isEmpty()) { right = ", " + right; } return left + subtreeRoot.data + right; } /** * Get the root node of the tree. For testing purposes only. * * @return the root node of the tree. */ public Node getRoot() { return this.root; } public static void main(String[] args) { BinarySearchTree t = new BinarySearchTree(); System.out.println(t); t.add("M"); System.out.println(t); t.add("G"); System.out.println(t); t.add("T"); System.out.println(t); t.add("D"); System.out.println(t); t.add("K"); System.out.println(t); t.add("X"); System.out.println(t); t.add("Z"); System.out.println(t); t.add("K"); System.out.println(t); t.add("K"); System.out.println(t); } }