package com.jadekler.datastructures;
import java.util.Stack;
/**
* This class holds items in a binary tree fashion, with red/black balancing
*/
public class RedBlackTree
{
private Node root;
private int numBlackNodesToDescendant;
class Node {
private Node left;
private Node right;
private Node parent;
private int num;
private boolean isRed;
public Node(int num) {
this.num = num;
this.isRed = false;
this.left = null;
this.right = null;
this.parent = null;
}
public Node(int num, boolean isRed) {
this.num = num;
this.isRed = isRed;
this.left = null;
this.right = null;
this.parent = null;
}
public boolean isRed() {
return this.isRed;
}
public boolean leftAndRightBlack() {
return (left == null || !left.isRed()) && (right == null || !right.isRed());
}
public int getNum() {
return this.num;
}
public Node getLeft() {
return this.left;
}
public Node getRight() {
return this.right;
}
public Node getParent() {
return this.parent;
}
public Node getSibling() {
if (this.parent != null) {
if (this.parent.getLeft() != this) {
return this.parent.getLeft();
} else {
return this.parent.getRight();
}
} else {
return null;
}
}
public void setIsRed(boolean isRed) {
this.isRed = isRed;
}
public void setLeft(Node node) {
this.left = node;
}
public void setRight(Node node) {
this.right = node;
}
public void setParent(Node node) {
this.parent = node;
}
}
public static void main(String args[]) {
RedBlackTree rbt = new RedBlackTree();
rbt.push(10);
rbt.push(85);
rbt.push(15);
rbt.push(70);
rbt.push(20);
}
public void push(int num) {
push(getRoot(), num);
emitTree();
System.out.println("\n\n\n\n");
}
public void push(Node node, int num) {
Node newNode = new Node(num);
newNode.setParent(node);
if (node == null) {
newNode.setIsRed(false);
setRoot(newNode);
} else {
if (num > node.getNum()) {
if (node.getRight() != null) {
push(node.getRight(), num);
} else {
insertNode(node, newNode, true);
}
} else {
if (node.getLeft() != null) {
push(node.getLeft(), num);
} else {
insertNode(node, newNode, false);
}
}
}
}
public void insertNode(Node parent, Node child, boolean insertRightSide) {
child.setIsRed(true);
if (insertRightSide) {
parent.setRight(child);
} else {
parent.setLeft(child);
}
}
/**
* Emits the tree visually in cli
* This function is based on camluca's 4954a1ad1d9b034abbd3c23c4581324fb6b8fa57
*/
public void emitTree()
{
Stack globalStack = new Stack();
globalStack.push(getRoot());
int errorCounter = 0;
int emptyLeaf = 32; // Just a guess at how wide this tree should be. Increase for larger trees
boolean isRowEmpty = false;
while(isRowEmpty == false && errorCounter < 500) {
Stack localStack = new Stack();
isRowEmpty = true;
for(int j = 0; j<emptyLeaf; j++)
System.out.print(' ');
while(globalStack.isEmpty() == false && errorCounter < 500) {
errorCounter++;
Node temp = (Node)globalStack.pop();
if(temp != null) {
this.emitNode(temp);
localStack.push(temp.getLeft());
localStack.push(temp.getRight());
if(temp.getLeft() != null || temp.getRight() != null)
isRowEmpty = false;
} else {
System.out.print("--");
localStack.push(null);
localStack.push(null);
}
for(int j = 0; j < emptyLeaf * 2 - 2 && errorCounter < 500; j++)
System.out.print(' ');
}
System.out.println();
emptyLeaf /= 2;
while(localStack.isEmpty() == false && errorCounter < 500)
globalStack.push( localStack.pop() );
}
}
/**
* Emits the node with system.out
* @param Node Node to emit
* @return void
*/
public void emitNode(Node node) {
if (node.isRed()) {
System.out.print(" "+node.getNum()+" ");
} else {
System.out.print("."+node.getNum()+".");
}
}
public Node getRoot() {
return this.root;
}
/**
* Sets the root for this binary tree
* @param node Root
* @return void
*/
public void setRoot(Node node) {
this.root = node;
}
}