JAVA 实现 - 红黑树

红黑树也是一种自平衡的二叉搜索树,较之AVL,插入和删除时旋转次数更少

红黑树特性:

  1. 所有节点都有两种颜色:红与黑
  2. 所有null 视为黑色
  3. 红色节点不能相邻
  4. 根节点时黑色
  5. 从根到任意一个叶子节点,路径中的黑色节点数一样(黑色完美平衡)

满足3,4,5 即位平衡

左旋

package com.datastructure.binarytree.redblacktree;

public class RedBlackTree {

    enum Color{
        RED,BALCK
    }

    private static class Node{
        int key;
        Object value;
        Node left;
        Node right;
        Node parent; //父节点
        Color color = Color.RED; //颜色

        //是否是左孩子
        boolean isLeftChild(){
            return parent != null && parent.left == this;
        }

        //返回叔叔节点
        Node uncle(){
            if(parent == null || parent.parent == null){
                return null;
            }
            if (isLeftChild()){
                return parent.parent.right;
            }else{
                return parent.parent.left;
            }
        }

        //返回兄弟节点
        Node sibling(){
            if (parent == null){
                return null;
            }
            if(isLeftChild()){
                return parent.right;
            }else{
                return parent.left;
            }
        }
    }

    //判断是否是红色节点
    public boolean isRed(Node node){
        return node != null && node.color == Color.RED;
    }

    //判断是否是黑色节点
    public boolean isBlack(Node node){
        return node == null || node.color == Color.BALCK;
    }

    Node root;

    /*
        右旋:
            1.获取粉色、黄色、绿色、节点 (粉色:下移;黄色:上移;绿色:换爹)
            2.三色节点的parent的处理
            3.旋转后新根的父节点的处理
     */
    private void rightRotate(Node pick){
        Node parent = pick.parent; //记录旋转前时粉色节点的父节点
        Node yellow = pick.left;
        Node green = yellow.right;

        if(green != null) {
            green.parent = pick;
        }

        yellow.right = pick;
        yellow.parent = parent;

        pick.left = green;
        pick.parent = yellow;

        //建立更上层节点的父子关系
        if (parent == null){
            root = yellow;
        } else if(parent.left == pick){
            parent.left = yellow;
        }else{
            parent.right = yellow;
        }
    }


    private void leftRotate(){

    }
  
}

插入节点

插入节点
情况1: 插入节点为根节点,将根节点变黑
情况2: 插入节点的父亲若为黑色,树的红黑性质不变,无须调整
插入节点的父亲为红色,触发红红相邻
情况3: 叔叔为红色
3.1 父亲变为黑色,为了保证黑色平衡,连带的叔叔也变为黑色
3.2 祖父如果是黑色不变,会造成这颗子树黑色过多,因此祖父节点变为红色
3.2 祖父如果变为红色,可能会触发红红相邻,因此将祖父进行递归调整
情况4: 叔叔为黑色
4.1 父亲为左孩子,插入节点也是左孩子,此时LL不平衡
4.2 父亲为左孩子,插入节点是右孩子,此时即LR不平衡
4.3 父亲为右孩子,插入节点也是后孩子,此时即RR不平衡
4.4 父亲为右孩子,插入节点是左孩子,此时即RL不平衡

情况4.1 平衡过程:
8,7,9,12,11 RL

情况4.2 平衡过程:
8,5,10,3,4 LR

package com.datastructure.binarytree.redblacktree;

public class RedBlackTree {

   ...

    public void put(int key, Object value) {
        Node curr = root;
        Node parent = null;
        while (curr != null) {
            parent = curr;
            if (key < curr.key) {
                curr = curr.left;
            } else if (curr.key < key) {
                curr = curr.right;
            } else {
                curr.value = value; //找到
                return;
            }
        }
        //没找到
        Node inserted = new Node(key, value);
        //找爹
        if (parent == null) { //空树
            root = inserted;
        } else if (key < parent.key) {
            parent.left = inserted;
            inserted.parent = parent;
        } else {
            parent.right = inserted;
            inserted.parent = parent;
        }

        fixRedRed(inserted); //处理红红
    }

    void fixRedRed(Node x) {
        if (x == root) {
            root.color = Color.BALCK;
            return;
        }

        if (isBlack(x.parent)) {
            return;
        }

        //触发红红相邻
        Node parent = x.parent;
        Node uncle = x.uncle();
        Node grandparent = parent.parent;
        if (isRed(uncle)) {
            //变色
            uncle.color = Color.BALCK;
            parent.color = Color.BALCK;
            grandparent.color = Color.RED;
            fixRedRed(grandparent);
            return;
        }

        //叔叔为黑色
        if (parent.isLeftChild() && x.isLeftChild()) { //LL不平衡
            parent.color = Color.BALCK;
            grandparent.color = Color.RED;
            rightRotate(grandparent);
        } else if (parent.isLeftChild() && !x.isLeftChild()) { //LR
            leftRotate(parent);
            x.color = Color.BALCK;
            grandparent.color = Color.RED;
            rightRotate(grandparent);
        } else if (!parent.isLeftChild() && !x.isLeftChild()) { //RR
            parent.color = Color.BALCK;
            grandparent.color = Color.RED;
            leftRotate(grandparent);
        } else { //RL
            rightRotate(parent);
            x.color = Color.BALCK;
            grandparent.color = Color.RED;
            rightRotate(grandparent);
        }
    }
}
posted @   chuangzhou  阅读(5)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示