:::::::::::::: KeyValue.java :::::::::::::: // Gary Yngve 10/30/2005 public class KeyValue { private int key; // simple integer key to avoid the complexities // of compareTo or a comparator public Object value; public KeyValue(int key, Object value) { this.key = key; this.value = value; } public int getKey() { // don't want other folks changing the key return key; } public String toString() { return "(" + key + "," + value + ")"; } } :::::::::::::: BinarySearchTree.java :::::::::::::: // Gary Yngve 10/30/2005 public class BinarySearchTree { // minimalistic TreeNode -- just left & right children -- no parent private static class TreeNode { KeyValue data; TreeNode left; TreeNode right; TreeNode(KeyValue data) { this(data,null,null); } TreeNode(KeyValue data, TreeNode left, TreeNode right) { this.data = data; this.left = left; this.right = right; } } // can only return one thing, so we need to wrap the two things we want // to return into a single class private static class ReturnWrap { KeyValue data; TreeNode node; ReturnWrap(KeyValue data, TreeNode node) { this.data = data; this.node = node; } } private TreeNode root; // base of the whole tree -- the public methods // call helper methods with root passed private int size; // number of elements in the tree public BinarySearchTree() { root = null; size = 0; } // pre: none // post: returns value if the key is found, null otherwise public Object get(int key) { return get(root,key); } // pre: none (though null value highly discouraged) // post: if key is found in tree, replaces old value with new value // and returns old value // if not found, adds to tree in proper place and returns null public Object put(int key, Object value) { ReturnWrap ret = put(root,new KeyValue(key,value)); root = ret.node; return ret.data; } // pre: none // post: if key is found in tree, removes that node. // returns the value removed public Object remove(int key) { ReturnWrap ret = remove(root,key); root = ret.node; return ret.data; } public void printInfix() { printInfix(root); } public int size() { return size; } public boolean isEmpty() { return size() == 0; } // pre: none // post: returns value if the key is found, null otherwise private Object get(TreeNode root, int key) { if (root == null) // key not found return null; else if (key == root.data.getKey()) // key is here return root.data.value; else if (key < root.data.getKey()) // search left return get(root.left,key); else // if (key > root.data.getKey()) // search right return get(root.right,key); } // pre: pair nonnull // post: if key is found in tree, replaces old value with new value // and returns old value along with root of tree. // if not found, adds to tree in proper place and returns null // along with root of tree. private ReturnWrap put(TreeNode root, KeyValue pair) { if (root == null) { // key not found; add new entry size++; return new ReturnWrap(null,new TreeNode(pair)); } else if (pair.getKey() == root.data.getKey()) { // replace entry ReturnWrap ret = new ReturnWrap(root.data,root); // return old data root.data = pair; return ret; } else if (pair.getKey() < root.data.getKey()) { // search left ReturnWrap ret = put(root.left,pair); root.left = ret.node; ret.node = root; return ret; } else { // if (pair.getKey() > root.data.getKey()) // search right ReturnWrap ret = put(root.right,pair); root.right = ret.node; ret.node = root; return ret; } } // pre: none // post: if key is found in tree, removes that node. // returns new root and the value removed private ReturnWrap remove(TreeNode root, int key) { if (root == null) // key not found return new ReturnWrap(null, null); else if (root.data.getKey() == key) { // key is here size--; ReturnWrap ret = new ReturnWrap(root.data,removeHere(root)); return ret; } else if (key < root.data.getKey()) { // search left ReturnWrap ret = remove(root.left,key); root.left = ret.node; ret.node = root; return ret; } else { // key > root.data.getKey() // search right ReturnWrap ret = remove(root.right,key); root.right = ret.node; ret.node = root; return ret; } } // pre: node1, node2 are nonnull // post: node1 and node2 have their .data swapped private void swapData(TreeNode node1, TreeNode node2) { KeyValue tmp = node1.data; node1.data = node2.data; node2.data = tmp; } // pre: root is to be removed from the tree // post: tree is restructured with root eliminated and still a BST, // and the new root is returned private TreeNode removeHere(TreeNode root) { if (root.left == null) // left not internal; easy return root.right; else if (root.right == null) // right not internal; easy return root.left; else { TreeNode node = root.right; if (node.left == null) { // next larger node is a right-child swapData(root,node); root.right = removeHere(root.right); // reduce to easy remove return root; } TreeNode parent; do { // next larger node is the leftmost descendent of right-child parent = node; node = node.left; } while(node.left != null); swapData(root,node); parent.left = removeHere(parent.left); // reduce to an easy remove return root; } } // pre: none // post: prints tree specified by root using an inorder traversal private void printInfix(TreeNode root) { if (root != null) { printInfix(root.left); System.out.println(root.data + "; L = " + (root.left==null?"null":root.left.data.toString()) + "; R = " + (root.right==null?"null":root.right.data.toString())); printInfix(root.right); } } } :::::::::::::: BSTTest.java :::::::::::::: // Gary Yngve 10/30/2005 public class BSTTest { public static void main(String[] arg) { BinarySearchTree bst = new BinarySearchTree(); bst.put(4,"dog"); bst.put(2,"bat"); bst.put(6,"fox"); bst.put(1,"ape"); bst.put(3,"cow"); bst.put(5,"elk"); bst.put(8,"hog"); bst.put(7,"goat"); bst.printInfix(); bst.remove(4); bst.printInfix(); } }