JAVA
- java 를 통한 AVL 구현
- AVL 회전
- RedBlack 이해
public class AVLTree<E extends Comparable<E>> extends BinarySearchTree<E> implements ITree<E>, BinaryTree.INodeCreator<E>{
private enum Balance {
LEFT_LEFT, LEFT_RIGHT, RIGHT_LEFT, RIGHT_RIGHT
};
public int height = 1;
public AVLTree(){
this.creator = this;
}
@Override
public boolean add(E data){
Node<E> t = super.addAndGetNode(data);
AVLNode<E> addedNode = (AVLNode<E>)t;
while(addedNode != null){
addedNode.updateHeight();
balnaceAfterInsert(addedNode);
addedNode = (AVLNode<E>) addedNode.parent;
}
return true;
}
@Override
public E remove(E data){
Node<E> nodeToRemoved = this.getNode(data);
if (nodeToRemoved != null) {
Node<E> replacementNode = this.getReplacementNode(nodeToRemoved);
AVLNode<E> nodeToRefactor = null;
if (replacementNode != null)
nodeToRefactor = (AVLNode<E>) replacementNode.parent;
if (nodeToRefactor == null)
nodeToRefactor = (AVLNode<E>) nodeToRemoved.parent;
if (nodeToRefactor != null && nodeToRefactor.equals(nodeToRemoved))
nodeToRefactor = (AVLNode<E>) replacementNode;
replaceNodeWithNode(nodeToRemoved, replacementNode);
if (nodeToRefactor != null) {
while (nodeToRefactor != null) {
nodeToRefactor.updateHeight();
balanceAfterDelete(nodeToRefactor);
nodeToRefactor = (AVLNode<E>) nodeToRefactor.parent;
}
}
}
return data;
}
private void balnaceAfterInsert(AVLNode<E> node){
int balanceFactor = node.getBalanceFactor();
if(balanceFactor < -1 || balanceFactor > 1){
AVLNode<E> parent = null;
AVLNode<E> child = null;
Balance balnace = null;
if(balanceFactor < 0){
parent = (AVLNode<E>)node.left;
balanceFactor = parent.getBalanceFactor();
if(balanceFactor < 0){
child = (AVLNode<E>)parent.left;
balnace = Balance.LEFT_LEFT;
}else{
child = (AVLNode<E>)parent.right;
balnace = Balance.LEFT_RIGHT;
}
}else{
parent = (AVLNode<E>)node.right;
balanceFactor = parent.getBalanceFactor();
if(balanceFactor < 0 ){
child = (AVLNode<E>)parent.left;
balnace = Balance.RIGHT_LEFT;
}else{
child = (AVLNode<E>)parent.right;
balnace = Balance.RIGHT_RIGHT;
}
}
print();
if(balnace == Balance.LEFT_LEFT){
System.out.println("LL");
rotateRight(node);
}else if(balnace == Balance.LEFT_RIGHT){
System.out.println("LR");
rotateLeft(parent);
print();
rotateRight(node);
print();
}else if(balnace == Balance.RIGHT_LEFT){
System.out.println("RL");
rotateRight(parent);
rotateLeft(node);
}else if(balnace == Balance.RIGHT_RIGHT){
System.out.println("RR");
rotateLeft(node);
}
print();
node.updateHeight();
child.updateHeight();
parent.updateHeight();
}
}
private void balanceAfterDelete(AVLNode<E> node) {
int balanceFactor = node.getBalanceFactor();
if (balanceFactor == -2 || balanceFactor == 2) {
if (balanceFactor == -2) {
}
else if(balanceFactor == 2){
}
}
}
@Override
public Node<E> createNewNode(E element, Node<E> parent) {
return (new AVLNode<E>(element, parent));
}
protected static class AVLNode<E extends Comparable<E>> extends Node<E>{
public int height = 1;
protected AVLNode(E element,Node<E> parent) {
super(element, parent);
}
protected void updateHeight() {
int leftHeight = 0;
int rightHeight = 0;
if (left != null) {
AVLNode<E> leftNode = (AVLNode<E>) left;
leftHeight = leftNode.height;
}
if (right != null) {
AVLNode<E> rightNode = (AVLNode<E>) right;
rightHeight = rightNode.height;
}
if (leftHeight > rightHeight) {
this.height = leftHeight + 1;
} else {
this.height = rightHeight + 1;
}
}
protected int getBalanceFactor(){
int leftHeight = 0;
int rightHeight = 0;
if(this.left != null){
AVLNode<E> avlNode = (AVLNode<E>)left;
leftHeight = avlNode.height;
}
if(this.right != null){
AVLNode<E> avlNode = (AVLNode<E>)right;
rightHeight = avlNode.height;
}
return rightHeight-leftHeight;
}
@Override
public String toString(){
return "element : " + element +" : height : "+ height+ " balanceFactor : " + getBalanceFactor();
}
}
}
public class RedBlackTree<E extends Comparable<E>> extends BinarySearchTree<E> implements ITree<E>, BinaryTree.INodeCreator<E>{
protected static final boolean BLACK = false;
protected static final boolean RED = true;
public RedBlackTree() {
this.creator = this;
}
@Override
public boolean add(E data){
RedBlackNode<E> nodeAdded = null;
boolean added = false;
if(root == null){
root = this.creator.createNewNode(data, null);
((RedBlackNode<E>) root).color = BLACK;
root.left = this.creator.createNewNode(null, root);
((RedBlackNode<E>) root.left).color = BLACK;
root.right = this.creator.createNewNode(null, root);
((RedBlackNode<E>) root.right).color = BLACK;
nodeAdded = (RedBlackNode<E>) root;
added = true;
}else{
Node<E> node = root;
while (node != null) {
if (node.element == null) {
node.element = data;
((RedBlackNode<E>) node).color = RED;
node.left = this.creator.createNewNode(null, node);
((RedBlackNode<E>) node.left).color = BLACK;
node.right = this.creator.createNewNode(null, node);
((RedBlackNode<E>) node.right).color = BLACK;
nodeAdded = (RedBlackNode<E>) 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<E> node) {
RedBlackNode<E> parent = (RedBlackNode<E>) node.parent;
if (parent == null) {
node.color = BLACK;
return;
}
if (parent.color == BLACK) {
return;
}
RedBlackNode<E> grandParent = node.getGrandParent();
RedBlackNode<E> uncle = node.getUncle();
if (parent.color == RED && uncle.color == RED) {
parent.color = BLACK;
uncle.color = BLACK;
if (grandParent != null) {
grandParent.color = RED;
balanceAfterInsert(grandParent);
}
} else {
if (parent.color == RED && uncle.color == BLACK) {
if (node.equals(parent.right) && parent.equals(grandParent.left)) {
rotateLeft(parent);
node = (RedBlackNode<E>) node.left;
grandParent = node.getGrandParent();
parent = (RedBlackNode<E>) node.parent;
uncle = node.getUncle();
} else if (node.equals(parent.left) && parent.equals(grandParent.right)) {
rotateRight(parent);
node = (RedBlackNode<E>) node.right;
grandParent = node.getGrandParent();
parent = (RedBlackNode<E>) node.parent;
uncle = node.getUncle();
}
}
if (parent.color == RED && uncle.color == BLACK) {
parent.color = BLACK;
grandParent.color = RED;
if (node.equals(parent.left) && parent.equals(grandParent.left)) {
rotateRight(grandParent);
} else if (node.equals(parent.right) && parent.equals(grandParent.right)) {
rotateLeft(grandParent);
}
}
}
}
@Override
public Node<E> createNewNode(E element, Node<E> parent) {
return (new RedBlackNode<E>(element, parent, BLACK));
}
protected static class RedBlackNode<E extends Comparable<E>> extends Node<E> {
protected boolean color = BLACK;
protected RedBlackNode(E element, Node<E> parent,boolean color) {
super(element, parent);
this.color = color;
}
protected RedBlackNode<E> getGrandParent() {
if (parent == null || parent.parent == null) return null;
return (RedBlackNode<E>) parent.parent;
}
protected RedBlackNode<E> getUncle() {
RedBlackNode<E> grandParent = getGrandParent();
if (grandParent == null) return null;
if (grandParent.left != null && grandParent.left.equals(parent)) {
return (RedBlackNode<E>) grandParent.right;
} else if (grandParent.right != null && grandParent.right.equals(parent)) {
return (RedBlackNode<E>) grandParent.left;
}
return null;
}
protected RedBlackNode<E> getSibling() {
if (parent == null) return null;
if (parent.left.equals(this)) {
return (RedBlackNode<E>) parent.right;
} else if (parent.right.equals(this)) {
return (RedBlackNode<E>) parent.left;
} else {
System.err.println("opps no sibling");
}
return null;
}
protected boolean isLeaf() {
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;
}
}
}