红黑树

性质

  • 节点是红色或者黑色

  • 根节点是黑色

  • 所有叶子节点都是黑色(叶子是NULL节点)

  • 每个红色节点的两个子节点都是黑色

  • 从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点

红黑树插入情景(插入节点为红色)

  • 红黑树为空树

  • 插入节点已存在

  • 插入节点的父节点是黑节点

  • 插入节点的父节点是红色

    • 插入节点的父节点是祖父节点的左节点

      • 插入节点的叔叔节点是红色

      • 插入节点的叔叔节点为黑色或者没有叔叔节点

        • 插入节点为父节点的左子节点

        • 插入节点为父节点的右节点

    • 插入节点的父节点是祖父节点的右节点

      • 插入节点的叔叔节点是红色

      • 插入节点的叔叔节点为黑色或者没有叔叔节点

        • 插入节点为父节点的右子节点

        • 插入节点为父节点的左子结点

红黑树插入重新平衡的方式

变色、左旋、右旋

红黑树的Java代码实现(插入操作)

public class RBTree {

    public static final Boolean RED = true;
    public static final Boolean Black = false;

    private Node root;

    // 节点
    static class Node {
        Node parent;
        Node left;
        Node right;
        int value;
        boolean color;

        public Node() {
        }

        public Node(Node parent, Node left, Node right, int value, boolean color) {
            this.parent = parent;
            this.left = left;
            this.right = right;
            this.value = value;
            this.color = color;
        }

        public Node(int value, boolean color) {
            this.value = value;
            this.color = color;
        }

        @Override
        public String toString() {
            return "Node{" +
                    "value=" + value +
                    ", color=" + color +
                    '}';
        }
    }

    // 先序遍历
    public void foreword() {
        foreword(this.root);
    }

    private void foreword(Node root) {

        if (root == null) {
            // System.out.println("该树为空树!");
            return;
        }
        System.out.println(root);
        if (root.left != null) {
            foreword(root.left);
        }
        if (root.right != null) {
            foreword(root.right);
        }

    }

    // 左旋
    public Node leftRotate(Node node) {
        if (node == null || node.right == null) {
            throw new RuntimeException("该节点不能进行左旋!");
        }

        Node tmp = node.right;
        tmp.parent = node.parent;
        if (node.parent != null) {
            if (node.parent.left == node) {
                node.parent.left = tmp;
            } else {
                node.parent.right = tmp;
            }
        }

        node.right = tmp.left;
        if (tmp.left != null) {
            tmp.left.parent = node;
        }
        tmp.left = node;
        node.parent = tmp;

        if (node == this.root) {
            this.root = tmp;
        }

        return tmp;

    }

    // 右旋
    public Node rightRotate(Node node) {
        if (node == null || node.left == null) {
            throw new RuntimeException("该节点不能进行右旋");
        }

        Node tmp = node.left;
        tmp.parent = node.parent;
        if (node.parent != null) {
            if (node.parent.left == node) {
                node.parent.left = tmp;
            } else {
                node.parent.right = tmp;
            }
        }

        node.left = tmp.right;
        if(tmp.right != null) {
            tmp.right.parent = node;
        }
        tmp.right = node;
        node.parent = tmp;

        if (node == this.root) {
            this.root = tmp;
        }

        return tmp;
    }

    // 查找节点
    public Node find(Node node) {
        return findParent(node.value, this.root);
    }

    private Node findParent(int value, Node node) {
//        if (value == node.value) {
//            return node;
//        }

        if (value > node.value) {
            if (node.right != null) {
                return findParent(value, node.right);
            } else {
                return node;
            }

        }

        if (value < node.value) {
            if (node.left != null) {
                return findParent(value, node.left);
            } else {
                return node;
            }
        }

        return node;
    }

    // 插入节点
    public void insert(Node node) {
        // 空树
        if (this.root == null) {
            this.root = node;
            node.color = Black;
            return;
        }

        Node temp = find(node);

        // 树中已经存在该节点
        if (node.value == temp.value) {
            return;
        }

        // 不是空树,且树中不存在该节点
        if (node.value < temp.value) {
            temp.left = node;
        }
        if (node.value > temp.value) {
            temp.right = node;
        }
        node.parent = temp;

        //修复树结构
        fixTree(node);

    }

    private void fixTree(Node node) {

        if (node == this.root) {
            node.color = Black;
            return;
        }

        Node parent = node.parent;
        Node grandFather = node.parent.parent;
        if (grandFather == null) {
            return;
        }
        Node uncle;
        if (grandFather.left == parent) {
            uncle = grandFather.right;
        } else {
            uncle = grandFather.left;
        }

        // 父节点为空
        if (parent.color == RED) {
            // 叔叔节点为空或颜色为黑色
            if (uncle == null || uncle.color == Black) {

                // 父亲节点位于祖父的左节点
                if (parent == grandFather.left) {

                    parent.color = Black;
                    grandFather.color = RED;

                    // node 是父节点的左节点
                    if(node == parent.left) {
                        leftRotate(grandFather);
                        fixTree(grandFather);
                    } else {
                        rightRotate(parent);
                        leftRotate(grandFather);
                        fixTree(grandFather);
                    }

                } else {
                    parent.color = Black;
                    grandFather.color = RED;

                    if(node == parent.left) {
                        rightRotate(parent);
                        leftRotate(grandFather);
                        fixTree(grandFather);
                    } else {
                        leftRotate(grandFather);
                        fixTree(grandFather);
                    }
                }
            } else {
                parent.color = Black;
                uncle.color = Black;
                grandFather.color = RED;
                fixTree(grandFather);
            }
        }
    }
}

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值