public class RedBlackTree> extends BinarySearchTree implements ITree, BinaryTree.INodeCreator{
protected static final boolean BLACK = false;
protected static final boolean RED = true;
public RedBlackTree() {
this.creator = this;
}
@Override
public boolean add(E data){
RedBlackNode nodeAdded = null;
boolean added = false;
if(root == null){
root = this.creator.createNewNode(data, null);
((RedBlackNode) root).color = BLACK;
root.left = this.creator.createNewNode(null, root);
((RedBlackNode) root.left).color = BLACK;
root.right = this.creator.createNewNode(null, root);
((RedBlackNode) root.right).color = BLACK;
nodeAdded = (RedBlackNode) root;
added = true;
}else{
Node node = root;
while (node != null) {
if (node.element == null) {
node.element = data;
((RedBlackNode) node).color = RED;
node.left = this.creator.createNewNode(null, node);
((RedBlackNode) node.left).color = BLACK;
node.right = this.creator.createNewNode(null, node);
((RedBlackNode) node.right).color = BLACK;
nodeAdded = (RedBlackNode) node;
added = true;
break;
}else if (data.compareTo(node.element) <= 0) {
node = node.left;
} else {
node = node.right;
}
}
}
if (added == true) {
balanceAfterInsert(nodeAdded);
}
return true;
}
private void balanceAfterInsert(RedBlackNode node) {
RedBlackNode parent = (RedBlackNode) node.parent;
if (parent == null) {
// 1.íì¬ë
¸ëì 루í¸
node.color = BLACK;
return;
}
if (parent.color == BLACK) {
// 2. íì¬ë
¸ëì ë¶ëª¨ê° ë¸ë => 문ì ìë¤.
return;
}
RedBlackNode grandParent = node.getGrandParent();
RedBlackNode uncle = node.getUncle();
if (parent.color == RED && uncle.color == RED) {
// 3. ë¶ëª¨ì ì¼ì¶ì´ 모ë RED => ëì¬ë 모ë ë¸ëì´ëê³ í 머ë를 ë ëë¡
parent.color = BLACK;
uncle.color = BLACK;
if (grandParent != null) {
grandParent.color = RED;
balanceAfterInsert(grandParent);
}
} else {
if (parent.color == RED && uncle.color == BLACK) {
// 4. ë¶ëª¨ë ë ë ì¼ì´ì ë¸ë
// ë¶ëª¨ì ì¤ë¥¸ìª½ì ìë ë
¸ëë¼ë©´, ìë§ê° í 머ëì ì¼ìª½ì ìë¤ë©´
if (node.equals(parent.right) && parent.equals(grandParent.left)) {
// right-left
rotateLeft(parent);
node = (RedBlackNode) node.left;
grandParent = node.getGrandParent();
parent = (RedBlackNode) node.parent;
uncle = node.getUncle();
} else if (node.equals(parent.left) && parent.equals(grandParent.right)) {
// left-right
rotateRight(parent);
node = (RedBlackNode) node.right;
grandParent = node.getGrandParent();
parent = (RedBlackNode) node.parent;
uncle = node.getUncle();
}
}
if (parent.color == RED && uncle.color == BLACK) {
// 5. ë¶ëª¨ê° ë ë ì¼ì´ì´ ë¸ë
parent.color = BLACK;
grandParent.color = RED;
if (node.equals(parent.left) && parent.equals(grandParent.left)) {
// left-left
rotateRight(grandParent);
} else if (node.equals(parent.right) && parent.equals(grandParent.right)) {
// right-right
rotateLeft(grandParent);
}
}
}
}
@Override
public Node createNewNode(E element, Node parent) {
return (new RedBlackNode(element, parent, BLACK));
}
protected static class RedBlackNode> extends Node {
protected boolean color = BLACK;
protected RedBlackNode(E element, Node parent,boolean color) {
super(element, parent);
this.color = color;
}
protected RedBlackNode getGrandParent() {
if (parent == null || parent.parent == null) return null;
return (RedBlackNode) parent.parent;
}
protected RedBlackNode getUncle() {
RedBlackNode grandParent = getGrandParent();
if (grandParent == null) return null;
if (grandParent.left != null && grandParent.left.equals(parent)) {
// ë¶ëª¨ìê° í 머ëì ì¼ìª½ì ìë¤ë©´ => ì¼ì´ì ì¤ë¥¸ìª½
return (RedBlackNode) grandParent.right;
} else if (grandParent.right != null && grandParent.right.equals(parent)) {
// ë¶ëª¨ìê° í 머ëì ì¤ë¥¸ìª½ì ìë¤ë©´ => ì¼ì´ì ì¼ìª½
return (RedBlackNode) grandParent.left;
}
return null;
}
protected RedBlackNode getSibling() {
if (parent == null) return null;
if (parent.left.equals(this)) {
// ë´ê° ë¶ëª¨ì ì¼ìª½ì´ë¼ë©´ íì¬ì매ë ì¤ë¥¸ìª½
return (RedBlackNode) parent.right;
} else if (parent.right.equals(this)) {
// ë´ê° ë¶ëª¨ì ì¤ë¥¸ìª½ì´ë¼ë©´ íì¬ì매ë ì¼ìª½
return (RedBlackNode) parent.left;
} else {
System.err.println("opps no sibling");
}
return null;
}
protected boolean isLeaf() {
// RedBlack ììë ìì 모ë null ì´ë©´ leat
if (left != null) return false;
if (right != null) return false;
return true;
}
@Override
public String toString(){
String colorStr = color == BLACK ? "BLACK" : "RED";
return "element : " + element +" : COLOR : " + colorStr;
}
}
}