public static void main(String[] args) { TreeNode<String> leftTree = new TreeNode<String>("B", new TreeNode<String>("D"), new TreeNode<String>("E")); TreeNode<String> rightTree = new TreeNode<String>("C", new TreeNode<String>("F"), new TreeNode<String>("G")); TreeNode<String> root = new TreeNode<String>("A", leftTree, rightTree); //now what? }
//note: overly simplistic -- no spacers between elements public static <E> String toStringInOrder(TreeNode<E> n) { if (n == null) { return ""; }else { String str = ""; str += toStringInOrder(n.getLeft()); str += n.getData(); str += toStringInOrder(n.getRight()); return str; } }
In main:
//now what?
System.out.println(toStringInOrder(root)); //prints? DBEAFCG
//note: overly simplistic -- no spacers between elements public static <E> String toStringPreOrder(TreeNode<E> n) { if (n == null) { return ""; }else { String str = ""; str += n.getData(); str += toStringPreOrder(n.getLeft()); str += toStringPreOrder(n.getRight()); return str; } }
In main:
//now what?
System.out.println(toStringPreOrder(root)); //prints? ABDECFG
//note: overly simplistic -- no spacers between elements public static <E> String toStringPostOrder(TreeNode<E> n) { if (n == null) { return ""; }else { String str = ""; str += toStringPostOrder(n.getLeft()); str += toStringPostOrder(n.getRight()); str += n.getData(); return str; } }
In main:
//now what?
System.out.println(toStringPostOrder(root)); //prints? DEBFGCA
public class BinarySearchTree<E extends Comparable<E>> { private TreeNode<E> root = null; private int size = 0; /** Creates an empty tree. */ public BinarySearchTree() { }
/** Adds the given item to this BST. */ public void add(E item) { this.size++; if (this.root == null) { //tree is empty, so just add item this.root = new TreeNode<E>(item); }else { //find where to insert, with pointer to parent node TreeNode<E> parent = null; TreeNode<E> curr = this.root; boolean wentLeft = true; while (curr != null) { //will execute at least once parent = curr; if (item.compareTo(curr.getData()) <= 0) { curr = curr.getLeft(); wentLeft = true; }else { curr = curr.getRight(); wentLeft = false; } } //now add new node on appropriate side of parent curr = new TreeNode<E>(item); if (wentLeft) { parent.setLeft(curr); }else { parent.setRight(curr); } } }
Iterative version. Rather long.
public void add(E item) { this.root = add(item, root); this.size++; } private TreeNode<E> add(E item, TreeNode<E> subtree) { if (subtree == null) { return new TreeNode<E>(item); }else { if (item.compareTo(subtree.getData()) <= 0) { subtree.setLeft(add(item, subtree.getLeft())); }else { subtree.setRight(add(item, subtree.getRight())); } return subtree; } }
@Override public String toString() { return toString(this.root); } private String toString(TreeNode<E> n) { if (n == null) { return " "; }else { String str = "["; str += toString(n.getLeft()); str += n.getData(); str += toString(n.getRight()); str += "]"; return str; } }
Multi-line output would be easier to read, but this clearly shows in-order traversal logic.
public static void main(String[] args) { BinarySearchTree<String> bst = new BinarySearchTree<String>(); System.out.println(bst); //prints: " " bst.add("G"); System.out.println(bst); //prints: [ G ] bst.add("D"); System.out.println(bst); //prints: [[ D ]G ] bst.add("B"); bst.add("C"); bst.add("L"); bst.add("M"); bst.add("H"); System.out.println(bst); //prints: [[[ B[ C ]]D ]G[[ H ]L[ M ]]] }
/** Returns the number of elements currently in this BST. */ public int size() { return this.size; }
/** * Returns first item from tree that is equivalent (according to compareTo) * to the given item. If item is not in tree, returns null. */ public E get(E item) { return get(item, this.root); } /** Finds it in the subtree rooted at the given node. */ private E get(E item, TreeNode<E> node) { if (node == null) { return null; }else if (item.compareTo(node.getData()) < 0) { return get(item, node.getLeft()); }else if (item.compareTo(node.getData()) > 0) { return get(item, node.getRight()); }else { //found it! return node.getData(); } }
Or similar code for a boolean contains(E item)
method.
/** Returns the greatest value (right-most node) of the given subtree. */ private E findMax(TreeNode<E> n) { if (n == null) { return null; //error case: no tree }else if (n.getRight() == null) { //can't go right any more, so this is max value return n.getData(); }else { return findMax(n.getRight()); } }
/** * Removes the first equivalent item found in the tree. * If item does not exist to be removed, throws IllegalArgumentException(). */ public void remove(E item) { this.root = remove(item, this.root); } private TreeNode<E> remove(E item, TreeNode<E> node) { if (node == null) { //didn't find item throw new IllegalArgumentException(item + " not found in tree."); }else if (item.compareTo(node.getData()) < 0) { //go to left, saving resulting changes made to left tree node.setLeft(remove(item, node.getLeft())); return node; }else if (item.compareTo(node.getData()) > 0) { //go to right, saving any resulting changes node.setRight(remove(item, node.getRight())); return node; }else { //found node to be removed! if (node.getLeft() == null && node.getRight() == null) { //leaf node return null; }else if (node.getRight() == null) { //has only a left child return node.getLeft(); }else if (node.getLeft() == null) { //has only a right child return node.getRight(); }else { //two children, so replace the contents of this node with max of left tree E max = findMax(node.getLeft()); //get max value node.setLeft(remove(max, node.getLeft())); //and remove its node from tree node.setData(max); return node; } } }