Forked from
cse332-23au / p2-public
25 commits behind the upstream repository.
-
Winston Jodjana authored1488e09e
BinarySearchTree.java 4.37 KiB
package cse332.datastructures.trees;
import cse332.datastructures.containers.Item;
import cse332.interfaces.misc.ComparableDictionary;
import cse332.interfaces.misc.SimpleIterator;
import cse332.interfaces.worklists.WorkList;
import datastructures.worklists.ArrayStack;
import java.lang.reflect.Array;
import java.util.Iterator;
/**
* BinarySearchTree implements the ComparableDictionary interface using a binary
* search tree. Notice that the key type must be Comparable.
*/
public class BinarySearchTree<K extends Comparable<? super K>, V>
extends ComparableDictionary<K, V> {
// The root of the BST. Root is null if and only if the tree is empty.
// This MUST be used as your root for any class that extends this
protected BSTNode root;
/**
* Create an empty binary search tree.
*/
public BinarySearchTree() {
super();
this.root = null;
}
/**
* Inner class to represent a node in the tree. Each node includes a data of
* type E and an integer count. The class is protected so that subclasses of
* BinarySearchTree can access it.
*/
public class BSTNode extends Item<K, V> {
public BSTNode[] children; // The children of this node.
/**
* Create a new data node.
*
* @param key
* key with which the specified value is to be associated
* @param value
* data element to be stored at this node.
*/
@SuppressWarnings("unchecked")
public BSTNode(K key, V value) {
super(key, value);
this.children = (BSTNode[]) Array.newInstance(BSTNode.class, 2);
}
}
protected BSTNode find(K key, V value) {
BSTNode prev = null;
BSTNode current = this.root;
int child = -1;
while (current != null) {
int direction = Integer.signum(key.compareTo(current.key));
// We found the key!
if (direction == 0) {
return current;
}
else {
// direction + 1 = {0, 2} -> {0, 1}
child = Integer.signum(direction + 1);
prev = current;
current = current.children[child];
}
}
// If value is not null, we need to actually add in the new value
if (value != null) {
current = new BSTNode(key, null);
if (this.root == null) {
this.root = current;
}
else {
assert(child >= 0); // child should have been set in the loop
// above
prev.children[child] = current;
}
this.size++;
}
return current;
}
@Override
public V find(K key) {
if (key == null) {
throw new IllegalArgumentException();
}
BSTNode result = find(key, null);
if (result == null) {
return null;
}
return result.value;
}
@Override
public V insert(K key, V value) {
if (key == null || value == null) {
throw new IllegalArgumentException();
}
BSTNode current = find(key, value);
V oldValue = current.value;
current.value = value;
return oldValue;
}
@Override
public Iterator<Item<K, V>> iterator() {
return new BSTIterator();
}
private class BSTIterator extends SimpleIterator<Item<K, V>> {
private BSTNode current;
private final WorkList<BSTNode> nodes;
public BSTIterator() {
this.nodes = new ArrayStack<BSTNode>();
if (BinarySearchTree.this.root != null) {
this.current = BinarySearchTree.this.root;
}
}
@Override
public boolean hasNext() {
return this.current != null || this.nodes.hasWork();
}
@Override
public Item<K, V> next() {
// Go left until we hit null
while (this.current != null) {
this.nodes.add(this.current);
this.current = this.current.children[0];
}
this.current = this.nodes.next();
Item<K, V> value = new Item<K, V>(this.current);
this.nodes.add(this.current.children[1]);
this.current = this.nodes.next();
return value;
}
}
}