1. 程式人生 > >老哥版紅黑樹

老哥版紅黑樹

紅黑樹

public class RBTree
{
Node root;

public RBTree()
{
    root = null;
}

public void add(int value)
{
    Node parent;
    Node thisNode = new Node(value);
    if (root != null) {
        parent = locateParentForAdd(value);
        if (parent == null) {
            return;
        } else {
            if (value > parent.value) {
                parent.rightChild = thisNode;
            } else if (value < parent.value) {
                parent.leftChild = thisNode;
            }
            thisNode.parent = parent;
        }
    } else {
        root = thisNode;
    }
    rbfy(thisNode);
}

public Node locateParentForAdd(int value)
{
    Node current = root;
    while (true) {
        if (value > current.value) {
            if (current.rightChild == null) {
                return current;
            } else {
                current = current.rightChild;
            }
        } else if (value < current.value) {
            if (current.leftChild == null) {
                return current;
            } else {
                current = current.leftChild;
            }
        } else {
            return null;
        }
    }
}

public Node searchNode(int value)
{
    Node current = root;
    if (root == null) {
        return null;
    }
    while (true) {
        if (value > current.value) {
            if (current.rightChild == null) {
                return null;
            } else {
                current = current.rightChild;
            }
        } else if (value < current.value) {
            if (current.leftChild == null) {
                return null;
            } else {
                current = current.leftChild;
            }
        } else {
            return current;
        }
    }
}

public void remove(int value)
{
    Node nodeToBeRemoved = locateNodeToBeRemoved(value);
    if (nodeToBeRemoved == null) {
        return;
    } else {
        if (nodeToBeRemoved.isRed()) {
            nodeToBeRemoved.delete();
        } else {
            removeBlackLeafNode(nodeToBeRemoved, true);
        }
    }
}

public void removeBlackLeafNode(Node current, boolean really)
{
    if (current.isRoot()) {
        if (really) {
            root = null;
        }
        return;
    }
    if (current.parent.isRed()) {
        current.parent.setBlack();
        current.getBrother().setRed();
        if (really) {
            current.delete();
        }
    } else if (current.getBrother().isRed()) {
        if (current.isLeftChild()) {
            leftRotate(current.parent);
        } else {
            rightRotate(current.parent);
        }
        current.parent.setRed();
        current.getBrother().setBlack();
        removeBlackLeafNode(current, true);
    } else if (current.getBrother().hasChild()) {
        if (current.isLeftChild() && current.getBrother().hasRightChild()) {
            leftRotate(current.parent);
            current.parent.getBrother().setBlack();
            if (really) {
                current.delete();
            }
        } else if (current.isRightChild() && current.getBrother().hasLeftChild()) {
            rightRotate(current.parent);
            current.parent.getBrother().setBlack();
            if (really) {
                current.delete();
            }
        } else if (current.isLeftChild() && current.getBrother().hasLeftChild()) {
            rightRotate(current.getBrother());
            current.getBrother().setBlack();
            current.getBrother().rightChild.setRed();
            removeBlackLeafNode(current, true);
        } else if (current.isRightChild() && current.getBrother().hasRightChild()) {
            leftRotate(current.getBrother());
            current.getBrother().setBlack();
            current.getBrother().leftChild.setRed();
            removeBlackLeafNode(current, true);
        }
    } else {
        if (really) {
            current.delete();
        }
        current.getBrother().setRed();
        removeBlackLeafNode(current.parent, false);
    }
}

public Node locateNodeToBeRemoved(int value)
{
    Node originalNode = searchNode(value);
    if (originalNode == null) {
        return null;
    }
    if (originalNode.isLeaf()) {
        return originalNode;
    } else {
        return replaceAndGetEmptyNode(originalNode);
    }
}

public Node replaceAndGetEmptyNode(Node current)
{
    Node nodeToBeEmpty;
    if (current.hasLeftChild()) {
        nodeToBeEmpty = getRightMostNodeOfLeftTree(current);
    } else {
        nodeToBeEmpty = getLeftMostNodeOfRightTree(current);
    }
    current.value = nodeToBeEmpty.value;
    if (nodeToBeEmpty.isLeaf()) {
        return nodeToBeEmpty;
    } else {
        return replaceAndGetEmptyNode(nodeToBeEmpty);
    }
}

public Node getRightMostNodeOfLeftTree(Node current)
{
    current = current.leftChild;
    while (true) {
        if (current.hasRightChild()) {
            current = current.rightChild;
        } else {
            return current;
        }
    }
}

public Node getLeftMostNodeOfRightTree(Node current)
{
    current = current.rightChild;
    while (true) {
        if (current.hasLeftChild()) {
            current = current.leftChild;
        } else {
            return current;
        }
    }
}

public void rbfy(Node current)
{
    if (current.isRoot()) {
        current.setBlack();
        return;
    }
    Node parent = current.parent;
    if (parent.isBlack()) {
        return;
    }
    Node uncle = current.getUncle();
    Node grandParent = current.getGrandParent();
    if (uncle != null && uncle.isRed()) {
        grandParent.setRed();
        current.parent.setBlack();
        current.getUncle().setBlack();
        rbfy(grandParent);
    } else {
        boolean isLeftChild = current.isLeftChild();
        boolean isParentLeftChild = current.parent.isLeftChild();
        if (isLeftChild && isParentLeftChild) {
            rightRotate(grandParent);
            parent.setBlack();
            grandParent.setRed();
        } else if (!isLeftChild && !isParentLeftChild) {
            leftRotate(grandParent);
            parent.setBlack();
            grandParent.setRed();
        } else {
            if (isLeftChild) {
                rightRotate(parent);
            } else {
                leftRotate(parent);
            }
            rbfy(current);
        }
    }
}

public void rightRotate(Node current)
{
    Node parent = current.parent;
    boolean isLeftChild = false;
    if (parent != null) {
        isLeftChild = current.isLeftChild();
    }
    Node leftNode = current.leftChild;
    Node temp = leftNode.rightChild;
    leftNode.rightChild = current;
    current.parent = leftNode;
    current.leftChild = temp;
    if (temp != null) {
        temp.parent = current;
    }
    if (parent != null) {
        if (isLeftChild) {
            parent.leftChild = leftNode;
        } else {
            parent.rightChild = leftNode;
        }
    } else {
        root = leftNode;
    }
    leftNode.parent = parent;
}

public void leftRotate(Node current)
{
    Node parent = current.parent;
    boolean isLeftChild = false;
    if (parent != null) {
        isLeftChild = current.isLeftChild();
    }
    Node rightNode = current.rightChild;
    Node temp = rightNode.leftChild;
    rightNode.leftChild = current;
    current.parent = rightNode;
    current.rightChild = temp;
    if (temp != null) {
        temp.parent = current;
    }
    if (parent != null) {
        if (isLeftChild) {
            parent.leftChild = rightNode;
        } else {
            parent.rightChild = rightNode;
        }
    } else {
        root = rightNode;
    }
    rightNode.parent = parent;
}

public void print()
{
    if (root != null) {
        _print(root);
    }
}

public void _print(Node current)
{
    if (current == null) {
        return;
    }
    Node leftChild = current.leftChild;
    Node rightChild = current.rightChild;
    _print(leftChild);
    System.out.println(current);
    _print(rightChild);
}

public static class Node
{
    public static final boolean RED = true;

    public static final boolean BLACK = false;

    public boolean color;

    public int value;

    public Node parent;

    public Node leftChild;

    public Node rightChild;

    public Node(int value)
    {
        this.value = value;
        this.color = RED;
        this.parent = null;
        this.leftChild = null;
        this.rightChild = null;
    }

    public boolean isLeftChild()
    {
        Node parent = this.parent;
        if (parent.leftChild == this) {
            return true;
        } else {
            return false;
        }
    }

    public boolean isRightChild()
    {
        Node parent = this.parent;
        if (parent.rightChild == this) {
            return true;
        } else {
            return false;
        }
    }

    public void delete()
    {
        if (isRoot()) {
            return;
        }
        Node parent = this.parent;
        if (isLeftChild()) {
            parent.leftChild = null;
        } else {
            parent.rightChild = null;
        }
    }

    public void setRed()
    {
        color = RED;
    }

    public void setBlack()
    {
        color = BLACK;
    }

    public boolean isRed()
    {
        if (color == RED) {
            return true;
        } else {
            return false;
        }
    }

    public boolean isBlack()
    {
        if (color == BLACK) {
            return true;
        } else {
            return false;
        }
    }

    public Node getGrandParent()
    {
        return this.parent.parent;
    }

    public Node getUncle()
    {
        Node parent = this.parent;
        Node grandParent = getGrandParent();
        if (parent.isLeftChild()) {
            return grandParent.rightChild;
        } else {
            return grandParent.leftChild;
        }
    }

    public boolean isLeaf()
    {
        if (leftChild == null && rightChild == null) {
            return true;
        } else {
            return false;
        }
    }

    public boolean hasLeftChild()
    {
        if (leftChild != null) {
            return true;
        } else {
            return false;
        }
    }

    public boolean hasRightChild()
    {
        if (rightChild != null) {
            return true;
        } else {
            return false;
        }
    }

    public Node getBrother()
    {
        Node parent = this.parent;
        if (isLeftChild()) {
            return parent.rightChild;
        } else {
            return parent.leftChild;
        }
    }

    public boolean hasChild()
    {
        if (leftChild != null || rightChild != null) {
            return true;
        } else {
            return false;
        }
    }

    public boolean isRoot()
    {
        if (parent == null) {
            return true;
        } else {
            return false;
        }
    }

    @Override
    public String toString()
    {
        String colorStr;
        if (isRed()) {
            colorStr = "red";
        } else {
            colorStr = "black";
        }
        StringBuilder builder = new StringBuilder(100);
        builder.append(colorStr);
        builder.append(value);
        builder.append(" - ");
        builder.append(parent);
        return builder.toString();
    }
}

public static void main(String[] agrs) throws Exception
{
    RBTree tree = new RBTree();

    tree.add(11);
    tree.add(2);
    tree.add(1);
    tree.add(7);
    tree.add(5);
    tree.add(8);
    tree.add(14);
    tree.add(15);
    tree.add(4);

    /*
    tree.remove(4);
    tree.remove(2);
    tree.remove(1);
    tree.remove(7);
    tree.remove(5);
    tree.remove(8);
    tree.remove(11);
    tree.remove(14);
    tree.remove(15);
    */

    tree.print();
}

}

老哥版紅黑樹