/*
   * case 1. item == null, not found.
   * case 2: item < node.data, search left.
   * case 3. item > node.data, search right.
   * case 4. item not in tree, do nothing.
   * case 5: item = node.data, remove it.
   * 		   		(a) if node has a single child, attach the child
   * 				to node's parent
   * 				(b) if node has two children,
   * 				replace node with the largest node in its left sub tree
   */
  private BSTNode remove(BSTNode node, int data) {
    if (node == null) {
      return node;
    }
    if (data < node.data) {
      node.left = remove(node.left, data);
      return node;
    }
    if (data > node.data) {
      node.right = remove(node.right, data);
      return node;
    } else {
      // Once item found, remove

      // If has single child, replace parent with child
      if (node.left == null) {
        return node.right;
      } else if (node.right == null) {
        return node.left;
      }
      // If has two children, replace the largest node on left
      else {
        node.data = findMax(node.left);
        return node;
      }
    }
  } // End remove(Node)
 private BSTNode insert(BSTNode node, int data) {
   if (node == null) {
     node = new BSTNode(data);
   } else {
     // This allows duplicates, however
     if (data <= node.data) {
       node.left = insert(node.left, data);
     } else {
       node.right = insert(node.right, data);
     }
   }
   return node;
 }
 /**
  * Return the largest child of the node parent which is the right most node in the left sub tree.
  */
 private int findMax(BSTNode parent) {
   if (parent.right.right == null) {
     int value = parent.right.data;
     parent.right = parent.right.left;
     return value;
   } else {
     return findMax(parent.right);
   }
 } // End findLargestChild(Node))