红黑树java实现

红黑树的性质

红黑树是一课二叉搜索树,它在每个结点上增加了一个存储位来表示结点的颜色,可以使RED或BLACK。通过对任何一条从根到叶子的简单路径上各个结点的颜色进行约束,红黑树确保没有一条路径会比其他路径长出2倍,因而是近似平衡的

树中每个结点包含5个属性:color、key、left、right、parent。如果一个结点没有子结点或父结点,则该结点相应属性的值为null。一棵红黑树是满足下面红黑性质的二叉搜索树:

  1. 每个结点或是红色的,或是黑色的;
  2. 根结点是黑色的;
  3. 每个叶结点是黑色的;
  4. 如果一个结点是红色的,则它的两个子结点都是黑色的;
  5. 对每个结点,从该结点到其所有后代叶结点的简单路径上,均包含相同数目的黑色结点。

为了便于处理红黑树代码中的边界条件,可以使用一个哨兵来代表null。对于一棵红黑树,哨兵是一个与树中的普通结点有相同属性的对象。它的color属性为BLACK,其他属性可以设置为任意值。如下图所示为一棵使用了哨兵的红黑树示例。
红黑树java实现_第1张图片

旋转

当对树执行插入或操作时,对树做了修改,所做的修改可能会导致树不满足红黑树的性质,因此需要进行旋转来维护红黑树的性质。旋转可分为左旋和右旋。下图展示了一棵子树旋转后的结果。
红黑树java实现_第2张图片

java代码实现

下面是使用java简单实现了红黑树,以及红黑树的插入和删除操作。

/**
 * 数据结构-红黑树
 */
public class RBTree {
    /**
     * 哨兵
     */
    private final Node sentinel = new Node(Color.BLACK);

    /**
     * 根节点
     */
    private Node root = sentinel;

    /**
     * 根据关键字搜索节点
     *
     * @param key 关键字
     * @return key所在的节点
     */
    public Node search(int key) {
        Node node = root;
        while (node != null && key != node.key) {
            // 如果key小于当前节点的key,则往左孩子节点找,否则往右孩子节点找
            if (key < node.key) {
                node = node.left;
            } else {
                node = node.right;
            }
        }
        return node;
    }

    /**
     * 插入关键字为key的节点
     *
     * @param key 关键字
     */
    public void insert(int key) {
        Node y = sentinel;
        Node x = root;
        while (x != sentinel) {
            y = x;
            if (key < x.key) {
                x = x.left;
            } else {
                x = x.right;
            }
        }
        Node newNode = new Node();
        newNode.key = key;
        newNode.parent = y;
        if (y == sentinel) {
            root = newNode;
        } else if (key < y.key) {
            y.left = newNode;
        } else {
            y.right = newNode;
        }
        newNode.left = sentinel;
        newNode.right = sentinel;
        newNode.color = Color.RED;
        insertFixUp(newNode);
    }


    /**
     * 删除关键字为key的节点
     *
     * @param key 关键字
     */
    public void delete(int key) {
        Node node = search(key);
        Node y = node;
        Color yOriginalColor = y.color;
        Node x;
        if (node.left == sentinel) {
            x = node.right;
            transplant(node, node.right);
        } else if (node.right == sentinel) {
            x = node.left;
            transplant(node, node.left);
        } else {
            y = min(node.right);
            yOriginalColor = y.color;
            x = y.right;
            if (y.parent == node) {
                x.parent = y;
            } else {
                transplant(y, y.right);
                y.right = node.right;
                y.right.parent = y;
            }
            transplant(node, y);
            y.left = node.left;
            y.left.parent = y;
            y.color = node.color;
        }
        if (yOriginalColor == Color.BLACK) {
            deleteFixUp(x);
        }
    }

    /**
     * 获取以node为根的子树中key最小的节点
     *
     * @param node 子树根节点
     * @return 子树中key最小的节点
     */
    public Node min(Node node) {
        while (node.left != null) {
            node = node.left;
        }
        return node;
    }

    public Node getRoot() {
        return root;
    }

    /**
     * 删除一个节点后,维护树的红黑性质
     *
     * @param node 节点
     */
    private void deleteFixUp(Node node) {
        while (node != root && node.color == Color.BLACK) {
            if (node == node.parent.left) {
                Node w = node.parent.right;
                if (w.color == Color.RED) {
                    w.color = Color.BLACK;
                    node.parent.color = Color.RED;
                    leftRotate(node.parent);
                    w = node.parent.right;
                }
                if (w.left.color == Color.BLACK && w.right.color == Color.BLACK) {
                    w.color = Color.RED;
                    node = node.parent;
                } else if (w.right.color == Color.BLACK) {
                    w.left.color = Color.BLACK;
                    w.color = Color.RED;
                    rightRotate(w);
                    w = node.parent.right;
                }
                w.color = node.parent.color;
                node.parent.color = Color.BLACK;
                w.right.color = Color.BLACK;
                leftRotate(node.parent);
                node = root;
            } else {
                Node w = node.parent.left;
                if (w.color == Color.RED) {
                    w.color = Color.BLACK;
                    node.parent.color = Color.RED;
                    leftRotate(node.parent);
                    w = node.parent.left;
                }
                if (w.right.color == Color.BLACK && w.left.color == Color.BLACK) {
                    w.color = Color.RED;
                    node = node.parent;
                } else if (w.left.color == Color.BLACK) {
                    w.right.color = Color.BLACK;
                    w.color = Color.RED;
                    leftRotate(w);
                    w = node.parent.left;
                }
                w.color = node.parent.color;
                node.parent.color = Color.BLACK;
                w.left.color = Color.BLACK;
                rightRotate(node.parent);
                node = root;
            }
        }
        node.color = Color.BLACK;
    }

    /**
     * 将node1替换成node2,以支持删除操作
     *
     * @param node1 节点1
     * @param node2 节点2
     */
    private void transplant(Node node1, Node node2) {
        if (node1.parent == sentinel) {
            root = node2;
        } else if (node1 == node1.parent.left) {
            node1.parent.left = node2;
        } else {
            node1.parent.right = node2;
        }
        node2.parent = node1.parent;
    }

    /**
     * 插入一个节点后,维护树的红黑性质
     *
     * @param node 插入的节点
     */
    private void insertFixUp(Node node) {
        while (node.parent.color == Color.RED) {
            if (node.parent == node.parent.parent.left) {
                Node temp = node.parent.parent.right;
                if (temp.color == Color.RED) {
                    node.parent.color = Color.BLACK;
                    temp.color = Color.BLACK;
                    node.parent.parent.color = Color.RED;
                    node = node.parent.parent;
                } else if (node == node.parent.right) {
                    node = node.parent;
                    leftRotate(node);
                } else {
                    node.parent.color = Color.BLACK;
                    node.parent.parent.color = Color.RED;
                    rightRotate(node.parent.parent);
                }
            } else {
                Node temp = node.parent.parent.left;
                if (temp.color == Color.RED) {
                    node.parent.color = Color.BLACK;
                    temp.color = Color.BLACK;
                    node.parent.parent.color = Color.RED;
                    node = node.parent.parent;
                } else if (node == node.parent.left) {
                    node = node.parent;
                    rightRotate(node);
                } else {
                    node.parent.color = Color.BLACK;
                    node.parent.parent.color = Color.RED;
                    leftRotate(node.parent.parent);
                }
            }
        }
        root.color = Color.BLACK;
    }

    /**
     * 在节点node上进行左旋操作
     *
     * @param node 节点
     */
    private void leftRotate(Node node) {
        Node right = node.right;
        // 将node的右子树的左子树放到node的右子树位置
        node.right = right.left;
        if (right.left != sentinel) {
            right.left.parent = node;
        }
        // 设置node的右子树的父节点为node的父节点
        right.parent = node.parent;
        if (node.parent == sentinel) {
            root = right;
        } else if (node == node.parent.left) {
            node.parent.left = right;
        } else {
            node.parent.right = right;
        }
        // 将node放到node的右子树的左子树位置
        right.left = node;
        node.parent = right;
    }

    /**
     * 在节点node上进行右旋操作
     *
     * @param node 节点
     */
    private void rightRotate(Node node) {
        Node left = node.left;
        node.left = left.right;
        if (left.right != sentinel) {
            left.right.parent = node;
        }
        left.parent = node.parent;
        if (node.parent == sentinel) {
            root = left;
        } else if (node == node.parent.right) {
            node.parent.right = left;
        } else {
            node.parent.left = left;
        }
        left.right = node;
        node.parent = left;
    }

    private enum Color {
        /**
         * 红色
         */
        RED,

        /**
         * 黑色
         */
        BLACK
    }

    public static class Node {
        /**
         * 节点颜色
         */
        private Color color;

        /**
         * 节点关键字
         */
        private int key;

        /**
         * 左孩子节点
         */
        private Node left;

        /**
         * 右孩子节点
         */
        private Node right;

        /**
         * 父节点
         */
        private Node parent;

        private Node() {
        }

        private Node(Color color) {
            this.color = color;
        }

        public Color getColor() {
            return color;
        }

        public int getKey() {
            return key;
        }

        public Node getLeft() {
            return left;
        }

        public Node getRight() {
            return right;
        }

        public Node getParent() {
            return parent;
        }
    }
}

你可能感兴趣的:(数据结构,java,数据结构)