/************************ BST.java ************************** * generic binary search tree */ public class BST { protected BSTNode root = null; public BST() { } public void clear() { root = null; } public boolean isEmpty() { return root == null; } public void insert(BaseObject el) { BSTNode p = root, prev = null; while (p != null) { // find a place for inserting new node; prev = p; if (p.key.isLessThan(el)) p = p.right; else p = p.left; } if (root == null) // tree is empty; root = new BSTNode(el); else if (prev.key.isLessThan(el)) prev.right = new BSTNode(el); else prev.left = new BSTNode(el); } public boolean isInTree(BaseObject el) { return search(el) != null; } public BaseObject search(BaseObject el) { return search(root,el); } protected BaseObject search(BSTNode p, BaseObject el) { while (p != null) if (el.equals(p.key)) return p.key; else if (el.isLessThan(p.key)) p = p.left; else p = p.right; return null; } public void preorder() { preorder(root); } public void inorder() { inorder(root); } public void postorder() { postorder(root); } protected void inorder(BSTNode p) { if (p != null) { inorder(p.left); p.visit(); inorder(p.right); } } protected void preorder(BSTNode p) { if (p != null) { p.visit(); preorder(p.left); preorder(p.right); } } protected void postorder(BSTNode p) { if (p != null) { postorder(p.left); postorder(p.right); p.visit(); } } public void deleteByCopying(BaseObject el) { BSTNode node, p = root, prev = null; while (p != null && !p.key.equals(el)) { // find the node p prev = p; // with element el; if (p.key.isLessThan(el)) p = p.right; else p = p.left; } node = p; if (p != null && p.key.equals(el)) { if (node.right == null) // node has no right child; node = node.left; else if (node.left == null) // no left child for node; node = node.right; else { BSTNode tmp = node.left; // node has both children; BSTNode previous = node; // 1. while (tmp.right != null) { // 2. find the rightmost previous = tmp; // position in the tmp = tmp.right; // left subtree of node; } node.key = tmp.key; // 3. overwrite the reference // of the key being deleted; if (previous == node) // if node's left child's previous.left = tmp.left; // right subtree is null; else previous.right = tmp.left; // 4. } if (p == root) root = node; else if (prev.left == p) prev.left = node; else prev.right = node; } else if (root != null) System.out.println("key " + el.toString() + " is not in the tree"); else System.out.println("the tree is empty"); } public void deleteByMerging(BaseObject el) { BSTNode tmp, node, p = root, prev = null; while (p != null && !p.key.equals(el)) { // find the node p prev = p; // with element el; if (p.key.isLessThan(el)) p = p.right; else p = p.left; } node = p; if (p != null && p.key.equals(el)) { if (node.right == null) // node has no right child: its left node = node.left; // child (if any) is attached to its parent; else if (node.left == null) // node has no left child: its right node = node.right; // child is attached to its parent; else { // be ready for merging subtrees; tmp = node.left; // 1. move left while (tmp.right != null) // 2. and then right as far as tmp = tmp.right; // possible; tmp.right = // 3. establish the link between the node.right; // the rightmost node of the left // subtree and the right subtree; node = node.left; // 4. } if (p == root) root = node; else if (prev.left == p) prev.left = node; else prev.right = node; } else if (root != null) System.out.println("key " + el.toString() + " is not in the tree"); else System.out.println("the tree is empty"); } public void iterativePreorder() { BSTNode p = root; Stack travStack = new Stack(); if (p != null) { travStack.push(p); while (!travStack.isEmpty()) { p = (BSTNode) travStack.pop(); p.visit(); if (p.right != null) travStack.push(p.right); if (p.left != null) // left child pushed after right travStack.push(p.left);// to be on the top of the stack; } } } public void iterativeInorder() { BSTNode p = root; Stack travStack = new Stack(); while (p != null) { while(p != null) { // stack the right child (if any) if (p.right != null) // and the node itself when going travStack.push(p.right); // to the left; travStack.push(p); p = p.left; } p = (BSTNode) travStack.pop(); // pop a node with no left child while (!travStack.isEmpty() && p.right == null) { // visit it and all p.visit(); // nodes with no right child; p = (BSTNode) travStack.pop(); } p.visit(); // visit also the first node with if (!travStack.isEmpty()) // a right child (if any); p = (BSTNode) travStack.pop(); else p = null; } } public void iterativePostorder() { BSTNode p = root, q = root; Stack travStack = new Stack(); while (p != null) { for ( ; p.left != null; p = p.left) travStack.push(p); while (p != null && (p.right == null || p.right == q)) { p.visit(); q = p; if (travStack.isEmpty()) return; p = (BSTNode) travStack.pop(); } travStack.push(p); p = p.right; } } public void breadthFirst() { BSTNode p = root; Queue queue = new Queue(); if (p != null) { queue.enqueue(p); while (!queue.isEmpty()) { p = (BSTNode) queue.dequeue(); p.visit(); if (p.left != null) queue.enqueue(p.left); if (p.right != null) queue.enqueue(p.right); } } } public void MorrisInorder() { BSTNode p = root, tmp; while (p != null) if (p.left == null) { p.visit(); p = p.right; } else { tmp = p.left; while (tmp.right != null && // go to the rightmost node of tmp.right != p) // the left subtree or tmp = tmp.right; // to the temporary parent of p; if (tmp.right == null) {// if 'true' rightmost node was tmp.right = p; // reached, make it a temporary p = p.left; // parent of the current root, } else { // else a temporary parent has been p.visit(); // found; visit node p and then cut tmp.right = null; // the right pointer of the current p = p.right; // parent, whereby it ceases to be } // a parent; } } public void MorrisPreorder() { BSTNode p = root, tmp; while (p != null) { if (p.left == null) { p.visit(); p = p.right; } else { tmp = p.left; while (tmp.right != null &&// go to the rightmost node of tmp.right != p) // the left subtree or tmp = tmp.right; // to the temporary parent of p; if (tmp.right == null) {// if 'true' rightmost node was p.visit(); // reached, visit the root and tmp.right = p; // make the rightmost node a temporary p = p.left; // parent of the current root, } else { // else a temporary parent has been tmp.right = null; // found; cut the right pointer of p = p.right; // the current parent, whereby it ceases } // to be a parent; } } } public void MorrisPostorder() { BSTNode p = new BSTNode(), tmp, q, r, s; p.left = root; while (p != null) if (p.left == null) p = p.right; else { tmp = p.left; while (tmp.right != null && // go to the rightmost node of tmp.right != p) // the left subtree or tmp = tmp.right; // to the temporary parent of p; if (tmp.right == null) {// if 'true' rightmost node was tmp.right = p; // reached, make it a temporary p = p.left; // parent of the current root, } else { // else a temporary parent has been found; // process nodes between p.left (included) and p (excluded) // extended to the right in modified tree in reverse order; // the first loop descends this chain of nodes and reverses // right pointers; the second loop goes back, visits nodes, // and reverses right pointers again to restore the pointers // to their original setting; for (q = p.left, r = q.right, s = r.right; r != p; q = r, r = s, s = s.right) r.right = q; for (s = q.right; q != p.left; q.right = r, r = q, q = s, s = s.right) q.visit(); p.left.visit(); // visit node p.left and then cut tmp.right = null; // the right pointer of the current p = p.right; // parent, whereby it ceases to be } // a parent; } } public void balance(BaseObject data[], int first, int last) { if (first <= last) { int middle = (first + last)/2; insert(data[middle]); balance(data,first,middle-1); balance(data,middle+1,last); } } }