红黑树-Java版

来源:互联网 发布:硬盘开盘数据恢复 编辑:程序博客网 时间:2024/06/07 04:58

先上代码-注释齐全

package com.uestc.rb;/** * 红黑树的Java实现 younfor@yeah.net *  * @author y * */// 定义颜色enum Color {    RED, BLACK}// 结点数据结构class Node {    private Node left;    private Node right;    private Node parent;    private Color color;    private int value;    public Node(Node left, Node right, Node parent, Color color, int value) {        this.left = left;        this.right = right;        this.parent = parent;        this.color = color;        this.value = value;    }    public Node() {    }    public Node(int value) {        this(null, null, null, null, value);    }    public Node getLeft() {        return left;    }    public void setLeft(Node left) {        this.left = left;    }    public Node getRight() {        return right;    }    public void setRight(Node right) {        this.right = right;    }    public Node getParent() {        return parent;    }    public void setParent(Node parent) {        this.parent = parent;    }    public Color getColor() {        return color;    }    public void setColor(Color color) {        this.color = color;    }    public int getValue() {        return value;    }    public void setValue(int value) {        this.value = value;    }}// 红黑树实现类public class RBTree {    // 定义空结点    private final Node NIL = new Node(null, null, null, Color.BLACK, -1);    // 定义根结点    private Node root = NIL;    /**     * 插入结点     *      * @param node     */    public void Insert(Node node) {        Node previous = NIL;        Node cur = root;        // 二叉搜索树寻找插入位置        while (cur != NIL) {            previous = cur;            if (cur.getValue() < node.getValue()) {                cur = cur.getRight();            } else {                cur = cur.getLeft();            }        }        node.setParent(previous);        // 设置父子联系-注意空树的情况        if (previous == NIL) {            root = node;            root.setParent(NIL);        } else if (previous.getValue() > node.getValue()) {            previous.setLeft(node);        } else {            previous.setRight(node);        }        node.setLeft(NIL);        node.setRight(NIL);        node.setColor(Color.RED);        InsertFixup(node);    }    /**     * 插入结点后的调整     *      * @param node     */    private void InsertFixup(Node node) {        // 黑父-pass        // 红父        while (node.getParent().getColor() == Color.RED) {            // 父亲是左孩子            if (node.getParent() == node.getParent().getParent().getLeft()) {                Node rightNuncle = node.getParent().getParent().getRight();                // 红父红叔                if (rightNuncle.getColor() == Color.RED) {                    rightNuncle.setColor(Color.BLACK);                    node.getParent().setColor(Color.BLACK);                    node.getParent().getParent().setColor(Color.RED);                    node = node.getParent().getParent();                }                // 红父黑叔                else {                    // 如果是右孩子先左旋                    if (node == node.getParent().getRight()) {                        //                        node = node.getParent();                        leftRotate(node);                    }                    // 右旋                    node.getParent().setColor(Color.BLACK);                    node.getParent().getParent().setColor(Color.RED);                    rightRotate(node.getParent().getParent());                }            } else {                // 父亲是右孩子-镜像                Node leftNuncle = node.getParent().getParent().getLeft();                if (leftNuncle.getColor() == Color.RED) {                    leftNuncle.setColor(Color.BLACK);                    node.getParent().setColor(Color.BLACK);                    node.getParent().getParent().setColor(Color.RED);                    node = node.getParent().getParent();                } else {                    if (node == node.getParent().getLeft()) {                        node = node.getParent();                        rightRotate(node);                    }                    node.getParent().setColor(Color.BLACK);                    node.getParent().getParent().setColor(Color.RED);                    leftRotate(node.getParent().getParent());                }            }        }        root.setColor(Color.BLACK);    }    /**     * 删除结点     * @param data     * @return     */    public Node Delete(int data) {        Node node = search(data);        if (node == null)            return null;        //真正被删除的结点        Node oldNode = NIL;        //删除后准备替代的结点        Node newNode = NIL;        if (node.getLeft() == NIL || node.getRight() == NIL) {            oldNode = node;        } else {            //当2个儿子的时候用后继(前驱也行)            oldNode = previous(node);        }        //设置替代结点关系        if (oldNode.getLeft() != NIL) {            newNode = oldNode.getLeft();        } else {            newNode = oldNode.getRight();        }        newNode.setParent(oldNode.getParent());        if (oldNode.getParent() == NIL) {            root = newNode;        } else if (oldNode == oldNode.getParent().getLeft()) {            oldNode.getParent().setLeft(newNode);        } else {            oldNode.getParent().setRight(newNode);        }        //交换真正删除的结点和替代结点的值(把node的值设置为oldNode的值,相当于真正把oldNode删掉了)        if (oldNode != node) {            node.setValue(oldNode.getValue());        }        //如果旧结点是红色,肯定是叶子结点,直接删了不用调整        //反之从新结点处开始调整        if (oldNode.getColor() == Color.BLACK) {            DeleteFixup(newNode);        }        return oldNode;    }    // 删除节点后的调整    private void DeleteFixup(Node node) {        //首先能走到这里,Old肯定是黑色        //下面讨论新结点情况        // 1.新结点红色直接变为黑色        // 2.新结点为黑色        while (node != root && node.getColor() == Color.BLACK) {            if (node == node.getParent().getLeft()) {            //新结点在父结点的左孩子                Node rightBrother = node.getParent().getRight();                //2.1 红兄                if (rightBrother.getColor() == Color.RED) { // case 1                                                            // node节点为左孩子,node节点的兄弟为RED                    rightBrother.setColor(Color.BLACK);                    node.getParent().setColor(Color.RED);                    leftRotate(node.getParent());                    rightBrother = node.getParent().getRight();                    //经过变化转换为黑兄了                }                //2.2 黑兄                //2.2.1 黑兄黑侄                if (rightBrother.getLeft().getColor() == Color.BLACK                        && rightBrother.getRight().getColor() == Color.BLACK) {                    rightBrother.setColor(Color.RED);                    node = node.getParent();                    //迭代-如果是红父直接会下次跳出,如果不是继续迭代                    continue;                } else if (rightBrother.getRight().getColor() == Color.BLACK) {                //2.2.2 黑兄红侄左                    rightBrother.getLeft().setColor(Color.BLACK);                    rightBrother.setColor(Color.RED);                    rightRotate(rightBrother);                    rightBrother = node.getParent().getRight();                    //转换为黑兄红侄右                } else {                //2.2.3 黑兄红侄右                    rightBrother.setColor(node.getParent().getColor());                    node.getParent().setColor(Color.BLACK);                    rightBrother.getRight().setColor(Color.BLACK);                    leftRotate(node.getParent());                    //为了跳出循环                    node = root;                }            } else {                Node leftBrother = node.getParent().getLeft();                if (leftBrother.getColor() == Color.RED) {                    leftBrother.setColor(Color.BLACK);                    node.getParent().setColor(Color.RED);                    rightRotate(node.getParent());                    leftBrother = node.getParent().getLeft();                }                if (leftBrother.getLeft().getColor() == Color.BLACK                        && leftBrother.getRight().getColor() == Color.BLACK) {                    leftBrother.setColor(Color.RED);                    node = node.getParent();                } else if (leftBrother.getLeft().getColor() == Color.BLACK) {                    leftBrother.setColor(Color.RED);                    leftBrother.getRight().setColor(Color.BLACK);                    leftRotate(leftBrother);                    leftBrother = node.getParent().getLeft();                } else {                    leftBrother.setColor(node.getParent().getColor());                    node.getParent().setColor(Color.BLACK);                    leftBrother.getLeft().setColor(Color.BLACK);                    rightRotate(node.getParent());                    node = root;                }            }        }        node.setColor(Color.BLACK);    }    /**     * 查找前驱结点     * @param node     * @return     */    public Node previous(Node node)    {        Node leftChild=node.getLeft();        if(leftChild!=NIL)        {            Node pre=null;            while(leftChild!=NIL)            {                pre=leftChild;                leftChild=leftChild.getRight();            }            return pre;        }else        {            Node parent=node.getParent();            while(parent!=NIL&&parent.getRight()!=node)            {                node=parent;                parent=parent.getParent();            }            return parent;        }    }    /**     * 查找后继结点     * @param node     * @return     */    public Node successor(Node node) {        Node rightChild = node.getRight();        if (rightChild != NIL) {            Node previous = null;            while (rightChild != NIL) {                previous = rightChild;                rightChild = rightChild.getLeft();            }            return previous;        } else {            Node parent = node.getParent();            while (parent != NIL && node != parent.getLeft()) {                node = parent;                parent = parent.getParent();            }            return parent;        }    }    /**     * 查找结点     *      * @param data     * @return     */    public Node search(int data) {        Node temp = root;        while (temp != NIL) {            if (temp.getValue() == data) {                return temp;            } else if (data < temp.getValue()) {                temp = temp.getLeft();            } else {                temp = temp.getRight();            }        }        return null;    }    /**     * 左旋     *      * @param node     *            不平衡点     */    private void leftRotate(Node node) {        Node rightNode = node.getRight();        // 1        node.setRight(rightNode.getLeft());        rightNode.getLeft().setParent(node);        rightNode.setParent(node.getParent());        // 2        if (node.getParent() == NIL) {            root = rightNode;        } else if (node == node.getParent().getLeft()) {            node.getParent().setLeft(rightNode);        } else {            node.getParent().setRight(rightNode);        }        // 3        rightNode.setLeft(node);        node.setParent(rightNode);    }    /**     * 右旋     *      * @param node     *            不平衡点     */    private void rightRotate(Node node) {        Node leftNode = node.getLeft();        // 1        node.setLeft(leftNode.getRight());        leftNode.getRight().setParent(node);        leftNode.setParent(node.getParent());        // 2        if (node.getParent() == NIL) {            root = leftNode;        } else if (node == node.getParent().getLeft()) {            node.getParent().setLeft(leftNode);        } else {            node.getParent().setRight(leftNode);        }        // 3        leftNode.setRight(node);        node.setParent(leftNode);    }    /**     * 输出     *      * @param node     */    public void print(Node node) {        if (node == NIL)            return;        print(node.getLeft());        System.out.println(" value:" + node.getValue() + " color:" + node.getColor());        print(node.getRight());    }    public Node getRoot() {        return root;    }}

下面是转载的介绍:
红黑树的平衡
红黑树首先是一棵二叉查找树,它每个结点都被标上了颜色(红色或黑色),红黑树满足以下5个性质:

1、 每个结点的颜色只能是红色或黑色。

2、 根结点是黑色的。

3、 每个叶子结点都带有两个空的黑色结点(被称为黑哨兵),如果一个结点n的只有一个左孩子,那么n的右孩子是一个黑哨兵;如果结点n只有一个右孩子,那么n的左孩子是一个黑哨兵。

4、 如果一个结点是红的,则它的两个儿子都是黑的。也就是说在一条路径上不能出现相邻的两个红色结点。

5、 对于每个结点来说,从该结点到其子孙叶结点的所有路径上包含相同数目的黑结点。
http://blog.csdn.net/very_2/article/details/5722682

0 0