package iiuf.util;
import java.util.Vector;
/**
Generic binary tree implementation.
(c) 1999, 2000, 2001, IIUF, DIUF<p>
@author $Author: ohitz $
@version $Name: $ $Revision: 1.1 $
*/
public class BinaryTree
extends
Tree
{
public BinaryTree() {
super(null);
}
protected BinaryTree(BinaryTreeNode NIL) {
super(NIL);
}
public void add(TreeNode z_) {
BinaryTreeNode z = (BinaryTreeNode)z_;
z.left = (BinaryTreeNode)NIL;
z.right = (BinaryTreeNode)NIL;
z.p = (BinaryTreeNode)NIL;
BinaryTreeNode y = (BinaryTreeNode)NIL;
BinaryTreeNode x = (BinaryTreeNode)root;
while(x != NIL) {
y = x;
if(z.key < x.key)
x = x.left;
else
x = x.right;
}
z.p = y;
if(y == NIL)
root = z;
else
if(((BinaryTreeNode)z).key < y.key)
((BinaryTreeNode)y).left = (BinaryTreeNode)z;
else
((BinaryTreeNode)y).right = (BinaryTreeNode)z;
changed();
}
public void remove(TreeNode z_) {
BinaryTreeNode z = (BinaryTreeNode)z_;
BinaryTreeNode y;
BinaryTreeNode x;
if(z.left == NIL || z.right == NIL)
y = z;
else
y = successor((BinaryTreeNode)z);
if(y.left != NIL)
x = y.left;
else
x = y.right;
if(x != NIL)
x.p = y.p;
if(y.p == NIL)
root = x;
else
if(((BinaryTreeNode)y.p).left == y)
((BinaryTreeNode)y.p).left = x;
else
((BinaryTreeNode)y.p).right = x;
if(y != z) {
y.p = z.p;
y.left = z.left;
y.right = z.right;
if(root == z)
root = y;
else {
if(((BinaryTreeNode)y.p).left == z)
((BinaryTreeNode)y.p).left = y;
else
((BinaryTreeNode)y.p).right = y;
}
if(y.left != NIL) y.left.p = y;
if(y.right != NIL) y.right.p = y;
}
z.p = NIL;
z.left = (BinaryTreeNode)NIL;
z.left = (BinaryTreeNode)NIL;
changed();
}
protected BinaryTreeNode successor(BinaryTreeNode x) {
if(x.right != NIL)
return minimum(x.right);
BinaryTreeNode y = (BinaryTreeNode)x.p;
while(y != NIL && x == y.right) {
x = y;
y = (BinaryTreeNode)y.p;
}
return y;
}
/**
Walks the tree in-order.
@param root Starting node.
@param handler The node handler.
@param misc Additional information passed to the handler.
*/
public void inorderWalk(TreeNode x, TreeWalk handler, Object misc) {
if(x != NIL) {
inorderWalk(((BinaryTreeNode)x).left, handler, misc);
handler.node(x, misc);
inorderWalk(((BinaryTreeNode)x).right, handler, misc);
}
}
protected BinaryTreeNode minimum(BinaryTreeNode x) {
while(x.left != NIL)
x = x.left;
return x;
}
protected BinaryTreeNode maximum(BinaryTreeNode x) {
while(x.right != NIL)
x = x.right;
return x;
}
public BinaryTreeNode get(BinaryTreeNode x, long k) {
while(x != NIL && k != x.key)
if(k < x.key)
x = x.left;
else
x = x.right;
return x;
}
public BinaryTreeNode minimum() {
return minimum((BinaryTreeNode)root);
}
public BinaryTreeNode maximum() {
return maximum((BinaryTreeNode)root);
}
public BinaryTreeNode get(long key) {
return get((BinaryTreeNode)root, key);
}
protected String verify() {
String result = super.verify();
// check sentinel
if(NIL != null) {
if(((BinaryTreeNode)NIL).left != null) {
System.out.println("Left of NIL has changed");
error();
}
if(((BinaryTreeNode)NIL).right != null) {
System.out.println("Right of NIL has changed");
error();
}
}
// Binary search tree property
//
// Let x be node in a binary search tree. If y is a node in the left
// subtree of x, then y.key <= x.key. If y is a node in the right subtree
// of x, then x.key <= y.key.
preorderWalk(root,
new TreeWalk() {
public void node(TreeNode node_, Object misc) {
BinaryTreeNode node = (BinaryTreeNode)node_;
if(node.left != NIL &&
!(node.key >= maximum(node.left).key)) {
System.out.println("Binary search tree property - violated (left)");
System.out.println(node);
error();
}
if(node.right != NIL &&
!(node.key <= minimum(node.right).key)) {
System.out.println("Binary search tree property - violated (right)");
System.out.println(node);
error();
}
}
}, null);
return result + "(BT,OK)";
}
protected static void test(int TEST_INIT_ELEMS, int TEST_RUNS, BinaryTree tree) {
Vector entries = new Vector();
try {
System.out.println("Initializing...(" + TEST_INIT_ELEMS + ")");
for(int i = 0; i < TEST_INIT_ELEMS; i++) {
BinaryTreeNode node = tree.newTestNode(Util.intRandom(1000));
entries.addElement(node);
tree.verify();
tree.add(node);
tree.verify();
}
System.out.println("Testing...(" + TEST_RUNS + ")");
for(int i = 0; i < TEST_RUNS; i++) {
int idx = Util.intRandom(entries.size());
if((idx & 1) == 0) {
BinaryTreeNode node = tree.newTestNode(Util.intRandom(1000));
entries.addElement(node);
tree.verify();
tree.add(node);
tree.verify();
}
else {
TreeNode node = tree.get(((BinaryTreeNode)entries.elementAt(idx)).key);
if(node == tree.nil()) {
System.out.println("Get failed.");
tree.error();
}
else {
entries.removeElement(node);
tree.verify();
tree.remove(node);
tree.verify();
}
}
}
int count = entries.size();
System.out.println("Cleanup...(" + count + ")");
for(int i = 0; i < count; i++) {
TreeNode node = (BinaryTreeNode)entries.elementAt(i);
tree.verify();
tree.remove(node);
tree.verify();
}
System.out.println("Final tree:" + tree);
} catch(Exception e) {
e.printStackTrace();
System.out.println(tree);
}
}
protected BinaryTreeNode newTestNode(long key) {
return new BinaryTreeNode(key, null);
}
public static void main(String[] argv) {
test(Integer.parseInt(argv[0]), Integer.parseInt(argv[1]), new BinaryTree());
}
}
/*
$Log: BinaryTree.java,v $
Revision 1.1 2002/07/11 12:00:11 ohitz
Initial checkin
Revision 1.2 2001/01/04 16:28:40 schubige
Header update for 2001 and DIUF
Revision 1.1 1999/10/07 11:02:12 schubige
Added red black and binary tree classes
*/