红黑树

红黑树RBTree
全称为RedBlackTree,本质上也是一棵二叉查找树,但它在二叉查找树的基础上增加了着色和相关的性质使得红黑树相对平衡,从而保证了红黑树的查找、插入、删除的时间复杂度最坏为O(logN)
红黑树是一种弱平衡二叉树,(极端情况下,某个节点的最长路径比最短路径大一倍), 相对于要求严格的AVL树来说,它的旋转次数少,所以红黑树的插入、删除操作比AVL树性能要高

红黑树的特点
(1) 每个结点或是红色的,或是黑色的
(2) 根节点是黑色的
(3) 每个叶子结点都是黑色的空节点(NULL)
(4) 如果一个结点是红的,那么它的两个子节点都是黑的
(5) 对于任意结点而言,其到叶子结点的每条路径都包含相同数目的黑结点

其中特性5,确保没有一条路径会比其他路径长出2倍,因此,红黑树是相对接近平衡的二叉树

红黑树举例
红黑树1.jpg

红黑树使用场景
(1) c++中的stl,map和set都是用红黑树实现的。
(2) linux进程调度, 用红黑树管理进程控制块。
(3) epoll在内核中的实现,用红黑树管理事件块
(4) nginx用红黑树管理timer
(5) java中treemap,treeset

节点x左旋,使得x变为y的左孩子,其中y原先为x的右孩子
红黑树-左旋1.jpg
private void leftRotate(RBTNode x) {
        RBTNode y = x.right; //获取当前要左旋节点x的右孩子节点,申明为y

        //设置y左孩子和节点x的关系
        x.right = y.left;
        if (y.left != null) {
            y.left.parent = x;
        }

        //修改y的父亲节点
        y.parent = x.parent;

        if (x.parent == null) {
            this.root = y;            //表示之前x是根节点
        } else {
            if (x.parent.left == x) {
                x.parent.left = y;    //表示之前x是一个左孩子
            }
            else {
                x.parent.right = y;    //表示之前x是一个右孩子
            }
        }

        //修改x和y的关系
        y.left = x;
        x.parent = y; 
    }

节点y右旋,使得y变为x的右孩子,其中x原先为y的左孩子, 这个过程正好跟左旋互逆
红黑树-右旋1.jpg
    private void rightRotate(RBTNode y) {
        RBTNode x = y.left; //获取当前要右旋节点y的左孩子节点,申明为x

        //设置x右孩子和节点y的关系
        y.left = x.right;
        if (x.right != null) {
            x.right.parent = y;
        }

        //修改x的父亲节点
        x.parent = y.parent;

        if (y.parent == null) {
            this.root = x;            //表示之前y是根节点
        } else {
            if (y == y.parent.right) {
                y.parent.right = x;    //表示之前y是一个右孩子
            }
            else {
                y.parent.left = x;    //表示之前y是一个左孩子
            }
        }

        //修改x和y的关系
        x.right = y;
        y.parent = x;
    }

左旋具体的例子
红黑树-左旋2.jpg

右旋具体的例子
红黑树-右旋2.jpg

红黑树的添加操作
将一个节点插入到红黑树中,需要执行哪些步骤呢?首先,将红黑树当作一颗二叉查找树,将节点插入;然后,将节点着色为红色;最后,通过旋转和重新着色等方法来修正该树,使之重新成为一颗红黑树。
红黑树本身就是一颗二叉查找树,将节点插入后,该树仍然是一颗二叉查找树。也就意味着,树的键值仍然是有序的。此外,无论是左旋还是右旋,若旋转之前这棵树是二叉查找树,旋转之后它一定还是二叉查找树。这也就意味着,任何的旋转和重新着色操作,都不会改变它仍然是一颗二叉查找树的事实。

红黑树的删除操作
将红黑树内的某一个节点删除。需要执行的操作依次是:首先,将红黑树当作一颗二叉查找树,将该节点从二叉查找树中删除;然后,通过"旋转和重新着色"等一系列来修正该树,使之重新成为一棵红黑树

你可能感兴趣的:(红黑树)