红黑树(待补充)

本文详细介绍了红黑树的特性,包括节点颜色规定和变色旋转规则,以及在Java中实现红黑树的插入操作和调整树结构的过程。
摘要由CSDN通过智能技术生成

红黑树特征:

节点是红色或黑色。
根节点是黑色。
每个叶子节点都是黑色的空节点(NIL节点)。
每个红色节点的两个子节点都是黑色。
从根节点到任一叶子节点的路径都包含相同数量的黑色节点。

变色旋转规则:

LR结构和RL结构要先进行旋转。
父节点是黑色,不用调整。
父节点是红色:
叔叔节点不存在,旋转当前节点的父节点与祖父节点,并将参与旋转的节点变色。
叔叔节点是红色,父节点和叔叔节点变为黑色,祖父节点变为红色。
叔叔节点是黑色,旋转当前节点的父节点与祖父节点,并将参与旋转的节点变色。

public class RedBlackTreeDemo {

    private static RedBlackNode root;

    public static void main(String[] args) {
        RedBlackTreeDemo redBlackTreeDemo = new RedBlackTreeDemo();
        redBlackTreeDemo.insert(10);
        redBlackTreeDemo.insert(20);
        redBlackTreeDemo.insert(30);
        redBlackTreeDemo.insert(40);
        redBlackTreeDemo.insert(50);
        redBlackTreeDemo.insert(60);
        redBlackTreeDemo.insert(70);
        redBlackTreeDemo.insert(80);
        redBlackTreeDemo.insert(90);
        redBlackTreeDemo.insert(100);
    }

    public void insert(int data) {
        RedBlackNode node = new RedBlackNode(data, null, null, null, Boolean.TRUE);
        if (root == null) {
            root = node;
            setBlack(root);
        } else {
            // 用于与插入节点进行比较
            RedBlackNode compareNode = root;
            // 记录插入节点的父节点
            RedBlackNode parent = null;
            while (compareNode != null) {
                parent = compareNode;
                if (data <= compareNode.getData()) {
                    compareNode = compareNode.getLeft();
                } else {
                    compareNode = compareNode.getRight();
                }
            }

            if (parent.getData() > data) {
                parent.setLeft(node);
            } else {
                parent.setRight(node);
            }

            node.setParent(parent);
            adjustTree(node);
        }
    }

    // 对节点进行变色和旋转
    public void adjustTree(RedBlackNode node) {

        // 当前进行校验的节点
        RedBlackNode currentNode = node;
        // 当前节点的父节点为红色且有父节点要循环向上校验节点
        while (currentNode.getParent() != null && currentNode.getParent().isRed()) {
            RedBlackNode parentNode = currentNode.getParent();
            RedBlackNode grandParentNode = parentNode.getParent();
            // 祖父节点为空,说明父节点就是根节点,把当前节点设置为根节点跳出循环
            if (grandParentNode == null && parentNode.equals(root)) {
                currentNode = parentNode;
                continue;
            }
            // 校验当前节点的父节点位置
            if (parentNode.equals(grandParentNode.getLeft())) {
                RedBlackNode uncleNode = grandParentNode.getRight();
                // 叔叔节点为空,以父节点为基旋转父节点和祖父节点
                if (uncleNode == null) {
                    // 父节点和当前节点为LL结构,正常进行旋转
                    if (currentNode.equals(parentNode.getLeft())) {
                        rightRotate(parentNode);
                        currentNode = grandParentNode;
                    } else {
                        // 父节点和当前节点为LR结构,先进行一次以当前节点为基进行旋转,无需改变当前节点继续进行校验
                        parentNode.setParent(currentNode);
                        node.setLeft(parentNode);
                    }
                } else if (uncleNode.isRed()) {
                    // 叔叔节点为红色,父节点和叔叔节点变色,祖父节点变色
                    changeColor(parentNode);
                    changeColor(uncleNode);
                    if (!grandParentNode.equals(root)) {
                        changeColor(grandParentNode);
                    }
                    currentNode = grandParentNode;
                } else {
                    // 叔叔节点为黑色,以父节点为基旋转父节点和祖父节点
                    rightRotate(parentNode);
                    currentNode = grandParentNode;
                }
            } else {
                RedBlackNode uncleNode = grandParentNode.getLeft();
                if (uncleNode == null) {
                    // 父节点和当前节点为RR结构,正常进行旋转
                    if (currentNode.equals(parentNode.getRight())) {
                        leftRotate(parentNode);
                        currentNode = grandParentNode;
                    } else {
                        // 父节点和当前节点为LR结构,先进行一次以当前节点为基进行旋转,无需改变当前节点继续进行校验
                        parentNode.setParent(currentNode);
                        node.setRight(parentNode);
                    }
                } else if (uncleNode.isRed()) {
                    // 叔叔节点为红色,父节点和叔叔节点变色,祖父节点变色
                    changeColor(parentNode);
                    changeColor(uncleNode);
                    if (!grandParentNode.equals(root)) {
                        changeColor(grandParentNode);
                    }
                    currentNode = grandParentNode;
                } else {
                    // 叔叔节点为黑色,以父节点为基旋转父节点和祖父节点
                    leftRotate(parentNode);
                    currentNode = grandParentNode;
                }
            }
        }
    }

    // 左旋
    public void leftRotate(RedBlackNode node) {
        RedBlackNode parentNode = node.getParent();
        RedBlackNode grandParentNode = parentNode.getParent();
        RedBlackNode currentLeftNode = node.getLeft();
        if (grandParentNode == null) {
            parentNode.setParent(node);
            parentNode.setRight(node.getLeft());
            node.setLeft(parentNode);
            node.setParent(null);
            root = node;
        } else {
            grandParentNode.setRight(node);
            node.setParent(grandParentNode);
            node.setLeft(parentNode);
            parentNode.setParent(node);
            parentNode.setRight(currentLeftNode);
        }
        // 对参与旋转的节点进行变色
        changeColor(node);
        changeColor(parentNode);
    }

    // 右旋
    public void rightRotate(RedBlackNode node) {
        RedBlackNode parentNode = node.getParent();
        RedBlackNode grandParentNode = parentNode.getParent();
        RedBlackNode currentRightNode = node.getLeft();
        if (grandParentNode == null) {
            parentNode.setParent(node);
            node.setRight(parentNode);
            node.setParent(null);
            root = node;
        } else {
            grandParentNode.setLeft(node);
            node.setParent(grandParentNode);
            node.setRight(parentNode);
            parentNode.setParent(node);
            parentNode.setLeft(currentRightNode);
        }
        // 对参与旋转的节点进行变色
        changeColor(node);
        changeColor(parentNode);
    }

    // 变色
    public void changeColor(RedBlackNode node) {
        if (node.isRed()) {
            setBlack(node);
        } else {
            setRed(node);
        }
    }

    public void setBlack(RedBlackNode node) {
        if (node != null) {
            node.setRed(Boolean.FALSE);
        }
    }

    public void setRed(RedBlackNode node) {
        if (node != null) {
            node.setRed(Boolean.TRUE);
        }
    }

    public class RedBlackNode {

        int data;
        RedBlackNode parent;
        RedBlackNode left;
        RedBlackNode right;
        boolean red;

        public RedBlackNode() {
        }

        public RedBlackNode(int data, RedBlackNode parent, RedBlackNode left, RedBlackNode right, boolean red) {
            this.data = data;
            this.parent = parent;
            this.left = left;
            this.right = right;
            this.red = red;
        }

        public int getData() {
            return data;
        }

        public void setData(int data) {
            this.data = data;
        }

        public RedBlackNode getParent() {
            return parent;
        }

        public void setParent(RedBlackNode parent) {
            this.parent = parent;
        }

        public RedBlackNode getLeft() {
            return left;
        }

        public void setLeft(RedBlackNode left) {
            this.left = left;
        }

        public RedBlackNode getRight() {
            return right;
        }

        public void setRight(RedBlackNode right) {
            this.right = right;
        }

        public boolean isRed() {
            return red;
        }

        public void setRed(boolean red) {
            this.red = red;
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值