/*
* Codeable Objects by Jennifer Jacobs is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
* Based on a work at hero-worship.com/portfolio/codeable-objects.
*
* This file is part of the Codeable Objects Framework.
*
* Codeable Objects is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Codeable Objects is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Codeable Objects. If not, see <http://www.gnu.org/licenses/>.
*/
package com.pixelmaid.dresscode.drawing.datatype;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
public class BinarySearchTree<E extends Comparable<? super E>> {
public Node<E> root;
public Vector<Vector<Node<E>>> levels = new Vector<Vector<Node<E>>>(0);
public int size = 0;
private int i;
public BinarySearchTree() {
}
public Node<E> add(E value) {
size++;
if (root == null) {
root = new Node<E>(value, null, this, 0);
root.column = 0;
root.name = "ROOT";
addNodeToLevel(root);
return root;
} else {
Node<E> node = root.add(value);
//myParent.println(node.level);
return node;
}
}
public void addNodeToLevel(Node<E> node) {
int level = node.level;
int column = -1;
//myParent.print("nodeLevel=");
//myParent.println(node.level);
if (levels.size() > level) {
//myParent.println("level exists");
Vector<Node<E>> selectedLevel = levels.get(level);
//myParent.print("selected Level =");
//myParent.println(selectedLevel);
//myParent.print("num of elements =");
//myParent.println(selectedLevel.size());
if (selectedLevel.size() == 0) {
selectedLevel.insertElementAt(node, 0);
} else if (node.value.compareTo(selectedLevel.get(0).value) == -1) {
//myParent.println("goes on start");
selectedLevel.insertElementAt(node, 0);
} else if (node.value.compareTo(selectedLevel.get(selectedLevel.size() - 1).value) == 1) {
//myParent.println("checking for end");
selectedLevel.addElement(node);
} else {
for (int i = 0; i < selectedLevel.size(); i++) {
if ((node.value.compareTo(selectedLevel.get(i).value) == 1) && (node.value.compareTo(selectedLevel.get(i + 1).value) == -1)) {
//myParent.println("insert in");
selectedLevel.insertElementAt(node, i + 1);
}
}
}
for (int i = 0; i < selectedLevel.size(); i++) {
selectedLevel.get(i).column = i;
}
} else {
//myParent.println("add new level");
Vector<Node<E>> newLevel = new Vector<Node<E>>(0);
newLevel.addElement(node);
addLevel(newLevel);
column = 0;
node.column = column;
}
}
//debugging function
private void checkNodesforNull() {
List<E> treeList = this.toList();
for (int i = 0; i < levels.size(); i++) {
for (int j = 0; j < levels.get(i).size(); j++) {
Node<E> testnode = levels.get(i).get(j);
testnode.column = j;
if (treeList.indexOf(testnode.value) == -1) {
System.out.println("node is not in tree at level ");
System.out.println(i);
System.out.println(" column ");
System.out.println(j);
}
}
}
}
//debugging function
private void checkRootNode(String alert) {
System.out.println("root column, " + alert + "=");
System.out.println(root.column);
if (root.column != 0) {
System.out.println("!!!ALERT!!! " + alert);
System.out.println("===================");
}
}
private boolean addLevel(Vector<Node<E>> level) {
levels.addElement(level);
//myParent.print("number of levels=");
//myParent.println(levels.size());
//myParent.println(levels.get(0));
return true;
}
public boolean remove(E _value) {
if (root == null)
return false;
else {
if (root.value.compareTo(_value) == 0) {
//rebuild tree!
E rootValue = root.value;
Vector<Vector<Node<E>>> subLevels = levels;
levels = new Vector<Vector<Node<E>>>(0);
root = null;
size = 0;
subLevels.remove(0);
for (int i = 0; i < subLevels.size(); i++) {
Vector<Node<E>> row = subLevels.get(i);
for (int j = 0; j < row.size(); j++) {
this.add(row.get(j).value);
}
}
subLevels = null;
return true;
} else {
int size = this.toList().size();
// myParent.print("size=");
// myParent.println(size);
Node<E> removedNode = root.remove(_value, null);
// myParent.print("removed node=");
// myParent.println(removedNode);
removeZeroedLevels();
size--;
// myParent.print("size=");
// myParent.println(size);
return true;
}
}
}
//called when node is removed to remove it from level and column lists
public void removeNodeFromLevels(Node<E> node) {
int level = node.level;
//myParent.print("node level=");
//myParent.println(level);
int column = node.column;
if (levels.size() > level) {
//myParent.print("node level size=");
//myParent.println(levels.get(level).size());
Vector<Node<E>> selectedLevel = levels.get(level);
selectedLevel.removeElement(node);
for (i = column; i < selectedLevel.size(); i++) {
selectedLevel.get(i).column = i;
}
//myParent.print("node level size removed=");
//myParent.println(levels.get(level).size());
//myParent.print("currentNumLevels=");
//myParent.println(levels.size());
}
}
public void removeZeroedLevels() {//removes any levels that have zero elements
for (i = 0; i < levels.size(); i++) {
Vector<Node<E>> levelList = levels.get(i);
if (levelList.size() == 0) { //element was last element in list, list must be removed
//myParent.print("level to be removedLevel=");
//myParent.println(i);
levels.removeElement(levelList);
levelList = null;
//myParent.println("element removed");
//myParent.print("newNumLevels=");
//myParent.println(levels.size());
}
}
}
private Node<E> insert(Node<E> node, E value) {
Node<E> result = new Node<E>(node);
int compare = result.value.compareTo(value);
if (compare == 0) {
return result;
}
if (compare > 0) {
if (result.getLeftChild() != null) {
result.setLeftChild(insert(result.getLeftChild(), value));
} else {
result.setLeftChild(new Node<E>(value, node, this, result.getLeftChild().level));
size++;
}
} else if (compare < 0) {
if (result.getRightChild() != null) {
result.setRightChild(insert(result.getRightChild(), value));
} else {
result.setRightChild(new Node<E>(value, node, this, result.getRightChild().level));
size++;
}
}
return result;
}
public Node<E> search(E _key) {
if (root == null)
return null;
else
//checkRootNode("search check");
return root.search(_key);
}
public List<E> toList() {
List<E> result = new ArrayList<E>();
treeToList(root, result);
return result;
}
private void treeToList(Node<E> node, List<E> goal) {
if (node != null) {
treeToList(node.getLeftChild(), goal);
goal.add(node.value);
treeToList(node.getRightChild(), goal);
}
}
}