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;
    }
  }
}