如何在一棵红黑树中插入一个节点

如何在一棵红黑树中插入一个节点

以普通的二叉搜索树的方式将新节点插入到树中。将新插入的节点标记为红色。根据红黑树的规则进行修复,使树重新成为红黑树

  1. 将新插入的节点标记为红色。

  2. 如果新插入的节点是根节点,将其颜色修正为黑色,即满足红黑树的性质2。

  3. 如果新插入的节点的父节点是黑色,不需要进行修复,树仍然是红黑树。

  4. 如果新插入的节点的父节点是红色,需要进行修复。
    a. 如果新插入的节点的叔叔节点是红色,表示父节点和叔叔节点都是红色,违反了红黑树的性质4。此时,将父节点和叔叔节点都改为黑色,将祖父节点改为红色,并以祖父节点为当前节点进行修复。
    b. 如果新插入的节点的叔叔节点是黑色或不存在,表示父节点是红色,叔叔节点是黑色或不存在,需要进行旋转操作来修复。
    i. 如果新插入的节点是其父节点的右子节点,并且父节点是其祖父节点的左子节点,此时需要进行左旋操作。即以父节点为支点进行左旋,将父节点变为当前节点,并以当前节点进行修复。
    ii. 如果新插入的节点是其父节点的左子节点,并且父节点是其祖父节点的左子节点,此时需要进行右旋操作。即以祖父节点为支点进行右旋,将祖父节点变为当前节点,并以当前节点进行修复。
    iii. 如果新插入的节点是其父节点的左子节点,并且父节点是其祖父节点的右子节点,此时需要进行先右旋后左旋的操作。即以父节点为支点进行右旋,将父节点变为当前节点,再以当前节点进行左旋,并将祖父节点变为当前节点进行修复。 iv. 如果新插入的节点是其父节点的右子节点,并且父节点是其祖父节点的右子节点,此时需要进行先左旋后右旋的操作。即以祖父节点为支点进行左旋,将祖父节点变为当前节点,再以当前节点进行右旋,并将祖父节点变为当前节点进行修复。

  5. 重复步骤4,直到修复完成。

// 定义红黑树节点颜色,RED为红色,BLACK为黑色
    enum Color {
        RED,
        BLACK
    }

    // 定义红黑树节点类
    class Node {
        int val;         // 节点值
        Node left;       // 左子节点
        Node right;      // 右子节点
        Node parent;     // 父节点
        Color color;     // 节点颜色

        // 构造函数
        public Node(int val) {
            this.val = val;
            this.color = Color.RED;  // 默认新插入节点为红色
        }
    }

    // 定义红黑树类
    class RedBlackTree {
        private Node root;   // 根节点
    
        // 构造函数
        public RedBlackTree() {
            this.root = null;
        }

        // 插入节点
        public void insert(int val) {
            Node newNode = new Node(val);  // 新建待插入节点
            if (root == null) {   // 如果根节点为空,将待插入节点设为根节点,颜色为黑色
                root = newNode;
                newNode.color = Color.BLACK;
            } else {
                Node current = root;   // 定义当前节点
                Node parent = null;    // 定义当前节点的父节点
                while (true) {
                    parent = current;
                    if (val < current.val) {  // 如果待插入值小于当前节点值,向左子树查找
                        current = current.left;
                        if (current == null) {   // 如果左子节点为空,将待插入节点设为左子节点
                            parent.left = newNode;
                            newNode.color = Color.RED;   // 新节点默认为红色
                            newNode = parent.left;
                            break;
                        }
                    } else {  // 如果待插入值大于或等于当前节点值,向右子树查找
                        current = current.right;
                        if (current == null) {  // 如果右子节点为空,将待插入节点设为右子节点
                            parent.right = newNode;
                            newNode.color = Color.RED;  // 新节点默认为红色
                            newNode = parent.right;
                            break;
                            }
                    }
                }
                // 调整红黑树的平衡
                fixUp(newNode);
            }
        }

        // 调整红黑树的平衡
        // 调整红黑树的平衡
        private void fixUp(Node newNode) {
            while (newNode != root && newNode.color == Color.RED && newNode.parent.color == Color.RED) {
                // 如果当前节点的父节点是祖父节点的左子节点
                if (newNode.parent == newNode.parent.parent.left) {
                    Node uncle = newNode.parent.parent.right;   // 定义叔节点
                    // 如果叔节点是红色,将当前节点、父节点、叔节点都设为黑色,祖父节点设为红色,然后将当前节点移动到祖父节点
                    if (uncle != null && uncle.color == Color.RED) {
                        uncle.color = Color.BLACK;
                        newNode.parent.color = Color.BLACK;
                        newNode.parent.parent.color = Color.RED;
                        newNode = newNode.parent.parent;
                    } else {  // 如果叔节点是黑色
                        // 如果当前节点是父节点的右子节点,先将当前节点设为父节点,然后左旋
                        if (newNode == newNode.parent.right) {
                            newNode = newNode.parent;
                            leftRotate(newNode);
                        }
                        // 将父节点设为黑色,祖父节点设为红色,然后右旋
                        newNode.parent.color = Color.BLACK;
                        newNode.parent.parent.color = Color.RED;
                        rightRotate(newNode.parent.parent);
                    }
                } else {  // 如果当前节点的父节点是祖父节点的右子节点
                    Node uncle = newNode.parent.parent.left;   // 定义叔节点
                    // 如果叔节点是红色,将当前节点、父节点、叔节点都设为黑色,祖父节点设为红色,然后将当前节点移动到祖父节点
                    if (uncle != null && uncle.color == Color.RED) {
                        uncle.color = Color.BLACK;
                        newNode.parent.color = Color.BLACK;
                        newNode.parent.parent.color = Color.RED;
                        newNode = newNode.parent.parent;
                    } else {  // 如果叔节点是黑色
                        // 如果当前节点是父节点的左子节点,先将当前节点设为父节点,然后右旋
                        if (newNode == newNode.parent.left) {
                            newNode = newNode.parent;
                            rightRotate(newNode);
                        }
                        // 将父节点设为黑色,祖父节点设为红色,然后左旋
                        newNode.parent.color = Color.BLACK;
                        newNode.parent.parent.color = Color.RED;
                        leftRotate(newNode.parent.parent);
                    }
                }
            }
            root.color = Color.BLACK;  // 根节点始终为黑色
        }

        // 左旋操作
        private void leftRotate(Node x) {
            Node y = x.right;
            x.right = y.left;
            if (y.left != null) {
                y.left.parent = x;
            }
            y.parent = x.parent;
            if (x.parent == null) {
                root = y;
            } else if (x == x.parent.left) {
                x.parent.left = y;
            } else {
                x.parent.right = y;
            }
            y.left = x;
            x.parent = y;
        }

        // 右旋操作
        private void rightRotate(Node x) {
            Node y = x.left;
            x.left = y.right;
            if (y.right != null) {
                y.right.parent = x;
            }
            y.parent = x.parent;
            if (x.parent == null) {
                root = y;
            } else if (x == x.parent.right) {
                x.parent.right = y;
            } else {
                x.parent.left = y;
            }
            y.right = x;
            x.parent = y;
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值