0
点赞
收藏
分享

微信扫一扫

【数据结构】红黑树Java实现

哈哈镜6567 2022-02-19 阅读 93

红黑树

1、特性

  • 所有节点均为黑色或者红色
  • 根节点为黑色
  • 所有为 NULL 的叶子节点都是黑色
  • 如果该节点是红色的,那么该节点的子节点一定都是黑色
  • 所有的 NULL 节点到根节点的路径上的黑色节点数量一定是相同的

2、操作

  • 左旋

​ 以某个结点作为支点(旋转结点),其右子结点变为旋转结点的父结点,右子结点的左子结点变为旋转结点的右子结点,左子结点保持不变。

/**
* 对目标节点进行左旋操作
*
* @param targetNode 目标节点
*/
private void leftRotate(RBNode<T> targetNode) {
    // 目标节点的右子节点,下面称右儿子
    RBNode<T> targetRightSon = targetNode.getRight();
    // 将目标节点的右子节点设置为右儿子的左子节点
    targetNode.setRight(targetRightSon.getLeft());
    // 如果右儿子的左子节点不为空,则需要将它的父节点设置为目标节点
    if (null != targetRightSon.getLeft()) {
        targetRightSon.getLeft().setParent(targetNode);
    }
    // 将右儿子的父节点设为目标节点的父节点
    targetRightSon.setParent(targetNode.getParent());
    // 如果目标节点的父节点为空,说明目标节点是父节点,左旋后父节点应该变为右儿子
    if (null == targetNode.getParent()) {
        root = targetRightSon;
    } else {
        // 如果目标节点不是父节点,需要判断目标节点为其父节点的左子节点还是右子节点,将右儿子替换进去
        if (targetNode.getParent().getLeft() == targetNode) {
            targetNode.getParent().setLeft(targetRightSon);
        } else {
            targetNode.getParent().setRight(targetRightSon);
        }
    }
    // 将右儿子的左子节点设置为目标节点
    targetRightSon.setLeft(targetNode);
    // 将目标节点的父节点设置为右儿子
    targetNode.setParent(targetRightSon);
}
  • 右旋

​ 以某个结点作为支点(旋转结点),其左子结点变为旋转结点的父结点,左子结点的右子结点变为旋转结点的左子结点,右子结点保持不变。

/**
* 对目标节点进行右旋操作
*
* @param targetNode 目标节点
*/
private void rightRotate(RBNode<T> targetNode) {
    // 目标节点的左子节点,下面称左儿子
    RBNode<T> targetLeftSon = targetNode.getLeft();
    // 将目标节点的左子节点设置为左儿子的右子节点
    targetNode.setLeft(targetLeftSon.getRight());
    // 如果左儿子的右节点不为空,则需要将它的父节点设置为目标节点
    if (null != targetLeftSon.getRight()) {
        targetLeftSon.getRight().setParent(targetNode);
    }
    // 将左儿子的父节点设置为目标节点的父节点
    targetLeftSon.setParent(targetNode.getParent());
    // 如果目标节点的父节点为空,说明目标节点是根节点,右旋后左二子应该变为父节点
    if (null == targetNode.getParent()) {
        root = targetLeftSon;
    } else {
        // 如果目标节点不是父节点,需要判断目标节点为其父节点的左子节点还是右子节点,将右儿子替换进去
        if (targetNode.getParent().getLeft() == targetNode) {
            targetNode.getParent().setLeft(targetLeftSon);
        } else {
            targetNode.getParent().setRight(targetLeftSon);
        }
    }
    // 将左儿子的右子节点设置为目标节点
    targetLeftSon.setRight(targetNode);
    // 将目标节点的父节点设置为左儿子
    targetNode.setParent(targetLeftSon);
}
  • 变色

​ 结点的颜色由红变黑或由黑变红。

3、插入

插入步骤

  • 第一步:按二插查找树将节点插入
  • 第二步:新插入节点置红
  • 第三步:通过旋转、变色等操作,使它重新成为红黑树
场景说明处理方式
情景一插入节点为根节点直接置黑
情景二插入节点的父节点为黑色无需处理
情景三父节点为红色,叔叔节点也为红色父节点置黑,叔叔节点置黑,祖父节点置红,将祖父节点设为当前节点,递归操作
情景四父节点为红色,叔叔节点为黑色,父节点为祖父节点的左孩子,当前节点为父节点的左孩子(LL)父节点置黑,祖父节点置红,对祖父节点右旋
情景五父节点为红色,叔叔节点为黑色,父节点为祖父节点的左孩子,当前节点为父节点的右孩子(LR)对父节点左旋,变成情景四(LL)处理
情景六父节点为红色,叔叔节点为黑色,父节点为祖父节点的右孩子,当前节点为父节点的右孩子(RR)父节点置黑,祖父节点置红,对祖父节点左旋
情景七父节点为红色,叔叔节点为黑色,父节点为祖父节点的右孩子,当前节点为父节点的左孩子(RL)对父节点右旋,变成情景六(RR)处理

本质就是将红色节点移动到根节点,然后置黑

/**
* 将结点插入到红黑树中
*
* @param newNode 插入的节点
*/
private void insert(RBNode<T> newNode) {
    int flag;
    RBNode<T> curr = null;
    RBNode<T> temp = root;
    // 找到新节点的父节点
    while (null != temp) {
        curr = temp;
        flag = newNode.getKey().compareTo(curr.getKey());
        if (flag < 0) {
            temp = temp.getLeft();
        } else {
            temp = temp.getRight();
        }
    }
    newNode.setParent(curr);
    // 判断找到的父节点是否为空
    if (null != curr) {
        // 比较新节点与父节点的大小,决定插左边还是右边
        flag = newNode.getKey().compareTo(curr.getKey());
        if (flag < 0) {
            curr.setLeft(newNode);
        } else {
            curr.setRight(newNode);
        }
    } else {
        // 为空,新节点成为父节点
        root = newNode;
    }

    // 重新修正
    insertFixUp(newNode);
}


/**
* 红黑树插入修正
*
* @param node 要插入的节点
*/
private void insertFixUp(RBNode<T> node) {
    // 生命父节点,祖父节点
    RBNode<T> parent;
    RBNode<T> grandParent;
    // 当插入节点父节点不为空, 且为红色时
    while ((parent = node.getParent()) != null && RED == parent.isColor()) {
        grandParent = parent.getParent();
        // 如果父节点是祖父节点左儿子
        if (grandParent.getLeft() == parent) {
            RBNode<T> uncle = grandParent.getRight();
            // Case1: 叔叔节点为红色
            if (null != uncle && RED == uncle.isColor()) {
                parent.setColor(BLACK);
                uncle.setColor(BLACK);
                grandParent.setColor(RED);
                node = grandParent;
                continue;
            }
            if (parent.getRight() == node) {
                // Case2: 叔叔节点为黑色,且当前节点为右孩子(LR——先对父节点左旋,变成LL处理)
                leftRotate(parent);
            }
            // Case3: 叔叔节点为黑色,且当前节点为左孩子(LL——父节点置黑,祖父节点置红,对祖父节点右旋)
            parent.setColor(BLACK);
            parent.getParent().setColor(BLACK);
            rightRotate(parent.getParent());
        } else {
            // 父节点是祖父节点的右儿子
            RBNode<T> uncle = grandParent.getLeft();
            // Case1: 叔叔节点是红色
            if (null != uncle && RED == uncle.isColor()) {
                parent.setColor(BLACK);
                uncle.setColor(BLACK);
                grandParent.setColor(RED);
                node = grandParent;
                continue;
            }
            if (parent.getLeft() == node) {
                // Case2: 叔叔节点为黑色,且当前节点是左孩子(RL——先对父节点右旋,变成RR处理)
                rightRotate(parent);
            }
            // Case3: 叔叔节点为黑色,且当前节点是右孩子(RR——父节点置黑,祖父节点置红,对祖父节点左旋)
            parent.setColor(BLACK);
            parent.getParent().setColor(RED);
            leftRotate(parent.getParent());
        }
    }
    // 根节点置黑
    root.setColor(BLACK);
}

4、删除

删除步骤

  • 第一步:将红黑树当做一颗二叉查找树,将节点删除
  • 第二步:通过旋转和变色使其重新变为红黑树

删除二叉查找树

  • 情况一:被删除节点为叶子结点,直接删除
  • 情况二:被删除节点只有一个子节点,删除该节点,用唯一的子节点代替他
  • 情况三:被删除的节点有两个子节点,则先找到其后继节点,把后继节点的值赋给它,然后把后继节点删除掉,其后继节点只可能为情况一或者情况二,按上面的步骤处理

修正操作

若替代节点为红色,无需处理,若为黑色有以下情况(讨论替代节点为左儿子情况,右儿子对称操作)

场景说明处理方式
场景一替代节点为父节点的左儿子(黑色),兄弟节点为红色父节点置红,兄弟节点置黑,左旋,更新兄弟节点
场景二替代节点为父节点的左儿子(黑色),兄弟节点为黑色,且左侄子节点,右侄子节点均为黑色兄弟节点置红,父节点设为新的替代节点递归
场景三替代节点为父节点的左儿子(黑色),兄弟节点为黑色,且左侄子节点为红色,右侄子节点为黑色兄弟节点置红,左侄子节点置黑,右旋,更新兄弟节点
场景四替代节点为父节点的左儿子(黑色),兄弟节点为黑色,右侄子节点为红色,左侄子节点颜色任意将父节点的颜色给到兄弟节点,父节点置黑,右侄子节点置黑,对P左旋,将替代节点指向root跳出循环
private void remove(RBNode<T> node) {
    if (null == node) {
        return;
    }
    RBNode<T> replaceNode;
    // Case1: 左右子树都不为空
    if (null != node.getLeft() && null != node.getRight()) {
        // 找到代替节点(中序遍历的后继节点,及右子树的最左节点)
        replaceNode = node;
        RBNode<T> temp = node.getRight();
        while (null != temp) {
            replaceNode = temp;
            temp = temp.getLeft();
        }
        // 找到代替节点,两者的值交换,删除代替节点
        T key = node.getKey();
        node.setKey(replaceNode.getKey());
        replaceNode.setKey(key);
        remove(replaceNode);
        return;
    }
    // Case2: 至少一个子树为空
    if (null != node.getLeft()) {
        replaceNode = node.getLeft();
    } else {
        replaceNode = node.getRight();
    }
    RBNode<T> parent = node.getParent();
    if (null == parent) {
        // 如果当前节点的父节点为空
        root = replaceNode;
        if (null != replaceNode) {
            replaceNode.setParent(null);
        }
    } else {
        // 如果当前节点的父节点不为空
        if (null != replaceNode) {
            replaceNode.setParent(parent);
        }
        if (parent.getLeft() == node) {
            parent.setLeft(replaceNode);
        } else {
            parent.setRight(replaceNode);
        }
    }
    // 如果删除的节点是黑色 会导致红黑树失衡 需要从新着色
    if (BLACK == node.isColor()) {
        removeFix(parent, replaceNode);
    }
}

/**
* 删除颜色调整
*
* @param parent      替代节点的父节点
* @param replaceNode 替代节点
*/
private void removeFix(RBNode<T> parent, RBNode<T> replaceNode) {
    while ((null == replaceNode || BLACK == replaceNode.isColor()) && root != replaceNode) {
        // 替代节点为父节点的左子节点
        if (parent.getLeft() == replaceNode) {
            RBNode<T> brother = parent.getRight();
            if (null != brother && RED == brother.isColor()) {
                // Case1: 兄弟节点为红色, 将父节点置红,兄弟节点置黑,父节点左旋
                brother.setColor(BLACK);
                parent.setColor(RED);
                leftRotate(parent);
                brother = parent.getRight();
            }
            if (brother == null || (isBlack(brother.getLeft()) && isBlack(brother.getRight()))) {
                // Case2: 兄弟节点黑 左侄子黑 右侄子黑, 将兄弟节点置红,父节点成为新的替代节点,继续递归
                if (null != brother) {
                    brother.setColor(RED);
                }
                replaceNode = parent;
                parent = parent.getParent();
                continue;
            }
            if (isRed(brother.getLeft())) {
                // Case3: 兄弟节点黑 左侄子红 右侄子黑, 将兄弟节点置红, 左侄子置黑 右旋兄弟节点
                brother.setColor(RED);
                brother.getLeft().setColor(BLACK);
                rightRotate(brother);
                // 更新兄弟节点
                brother = brother.getParent();
            }
            // Case4: S黑 B黑 BR红, 将父节点颜色给到B,父节点置黑, 右侄子节点置黑,父节点左旋,跳出循环
            brother.setColor(parent.isColor());
            brother.getRight().setColor(BLACK);
            parent.setColor(BLACK);
            leftRotate(parent);
            replaceNode = root;
        } else {
            // 替代节点为父节点的右子节点 和上面对称操作
            RBNode<T> brother = parent.getLeft();
            if (null != brother && RED == brother.isColor()) {
                brother.setColor(BLACK);
                parent.setColor(RED);
                rightRotate(parent);
                brother = parent.getLeft();
            }
            if (null == brother || (isBlack(brother.getLeft()) && isBlack(brother.getRight()))) {
                if (null != brother) {
                    brother.setColor(RED);
                }
                replaceNode = parent;
                parent = parent.getParent();
                continue;
            }
            if (isRed(brother.getRight())) {
                brother.setColor(BLACK);
                brother.getRight().setColor(BLACK);
                rightRotate(brother);
                brother = brother.getParent();
            }
            brother.setColor(parent.isColor());
            parent.setColor(BLACK);
            brother.getLeft().setColor(BLACK);
            rightRotate(parent);
            replaceNode = root;
        }

    }
    if (replaceNode != null) {
        replaceNode.setColor(BLACK);
    }
}

5、完整实现

package com.yuanjia.tree;

import lombok.Data;

@Data
public class RBTree<T extends Comparable<T>> {

    private RBNode<T> root;
    private final static boolean RED = false;
    private final static boolean BLACK = true;


    /**
     * 新建一个节点插入到红黑树中
     *
     * @param key 需要插入的值
     */
    public void insert(T key) {
        insert(new RBNode<>(RED, key, null, null, null));
    }

    /**
     * 将结点插入到红黑树中
     *
     * @param newNode 插入的节点
     */
    private void insert(RBNode<T> newNode) {
        int flag;
        RBNode<T> curr = null;
        RBNode<T> temp = root;
        // 找到新节点的父节点
        while (null != temp) {
            curr = temp;
            flag = newNode.getKey().compareTo(curr.getKey());
            if (flag < 0) {
                temp = temp.getLeft();
            } else {
                temp = temp.getRight();
            }
        }
        newNode.setParent(curr);
        // 判断找到的父节点是否为空
        if (null != curr) {
            // 比较新节点与父节点的大小,决定插左边还是右边
            flag = newNode.getKey().compareTo(curr.getKey());
            if (flag < 0) {
                curr.setLeft(newNode);
            } else {
                curr.setRight(newNode);
            }
        } else {
            // 为空,新节点成为父节点
            root = newNode;
        }

        // 重新修正
        insertFixUp(newNode);
    }

    /**
     * 红黑树插入修正
     *
     * @param node 要插入的节点
     */
    private void insertFixUp(RBNode<T> node) {
        // 生命父节点,祖父节点
        RBNode<T> parent;
        RBNode<T> grandParent;
        // 当插入节点父节点不为空, 且为红色时
        while ((parent = node.getParent()) != null && RED == parent.isColor()) {
            grandParent = parent.getParent();
            // 如果父节点是祖父节点左儿子
            if (grandParent.getLeft() == parent) {
                RBNode<T> uncle = grandParent.getRight();
                // Case1: 叔叔节点为红色
                if (null != uncle && RED == uncle.isColor()) {
                    parent.setColor(BLACK);
                    uncle.setColor(BLACK);
                    grandParent.setColor(RED);
                    node = grandParent;
                    continue;
                }
                if (parent.getRight() == node) {
                    // Case2: 叔叔节点为黑色,且当前节点为右孩子(LR——先对父节点左旋,变成LL处理)
                    leftRotate(parent);
                }
                // Case3: 叔叔节点为黑色,且当前节点为左孩子(LL——父节点置黑,祖父节点置红,对祖父节点右旋)
                parent.setColor(BLACK);
                parent.getParent().setColor(BLACK);
                rightRotate(parent.getParent());
            } else {
                // 父节点是祖父节点的右儿子
                RBNode<T> uncle = grandParent.getLeft();
                // Case1: 叔叔节点是红色
                if (null != uncle && RED == uncle.isColor()) {
                    parent.setColor(BLACK);
                    uncle.setColor(BLACK);
                    grandParent.setColor(RED);
                    node = grandParent;
                    continue;
                }
                if (parent.getLeft() == node) {
                    // Case2: 叔叔节点为黑色,且当前节点是左孩子(RL——先对父节点右旋,变成RR处理)
                    rightRotate(parent);
                }
                // Case3: 叔叔节点为黑色,且当前节点是右孩子(RR——父节点置黑,祖父节点置红,对祖父节点左旋)
                parent.setColor(BLACK);
                parent.getParent().setColor(RED);
                leftRotate(parent.getParent());
            }
        }
        // 根节点置黑
        root.setColor(BLACK);
    }


    public void remove(T key) {
        RBNode<T> node;
        if ((node = search(root, key)) != null) {
            remove(node);
        }
    }

    private void remove(RBNode<T> node) {
        if (null == node) {
            return;
        }
        RBNode<T> replaceNode;
        // Case1: 左右子树都不为空
        if (null != node.getLeft() && null != node.getRight()) {
            // 找到代替节点(中序遍历的后继节点,及右子树的最左节点)
            replaceNode = node;
            RBNode<T> temp = node.getRight();
            while (null != temp) {
                replaceNode = temp;
                temp = temp.getLeft();
            }
            // 找到代替节点,两者的值交换,删除代替节点
            T key = node.getKey();
            node.setKey(replaceNode.getKey());
            replaceNode.setKey(key);
            remove(replaceNode);
            return;
        }
        // Case2: 至少一个子树为空
        if (null != node.getLeft()) {
            replaceNode = node.getLeft();
        } else {
            replaceNode = node.getRight();
        }
        RBNode<T> parent = node.getParent();
        if (null == parent) {
            // 如果当前节点的父节点为空
            root = replaceNode;
            if (null != replaceNode) {
                replaceNode.setParent(null);
            }
        } else {
            // 如果当前节点的父节点不为空
            if (null != replaceNode) {
                replaceNode.setParent(parent);
            }
            if (parent.getLeft() == node) {
                parent.setLeft(replaceNode);
            } else {
                parent.setRight(replaceNode);
            }
        }
        // 如果删除的节点是黑色 会导致红黑树失衡 需要从新着色
        if (BLACK == node.isColor()) {
            removeFix(parent, replaceNode);
        }
    }

    /**
     * 删除颜色调整
     *
     * @param parent      替代节点的父节点
     * @param replaceNode 替代节点
     */
    private void removeFix(RBNode<T> parent, RBNode<T> replaceNode) {
        while ((null == replaceNode || BLACK == replaceNode.isColor()) && root != replaceNode) {
            // 替代节点为父节点的左子节点
            if (parent.getLeft() == replaceNode) {
                RBNode<T> brother = parent.getRight();
                if (null != brother && RED == brother.isColor()) {
                    // Case1: 兄弟节点为红色, 将父节点置红,兄弟节点置黑,父节点左旋
                    brother.setColor(BLACK);
                    parent.setColor(RED);
                    leftRotate(parent);
                    brother = parent.getRight();
                }
                if (brother == null || (isBlack(brother.getLeft()) && isBlack(brother.getRight()))) {
                    // Case2: 兄弟节点黑 左侄子黑 右侄子黑, 将兄弟节点置红,父节点成为新的替代节点,继续递归
                    if (null != brother) {
                        brother.setColor(RED);
                    }
                    replaceNode = parent;
                    parent = parent.getParent();
                    continue;
                }
                if (isRed(brother.getLeft())) {
                    // Case3: 兄弟节点黑 左侄子红 右侄子黑, 将兄弟节点置红, 左侄子置黑 右旋兄弟节点
                    brother.setColor(RED);
                    brother.getLeft().setColor(BLACK);
                    rightRotate(brother);
                    // 更新兄弟节点
                    brother = brother.getParent();
                }
                // Case4: S黑 B黑 BR红, 将父节点颜色给到B,父节点置黑, 右侄子节点置黑,父节点左旋,跳出循环
                brother.setColor(parent.isColor());
                brother.getRight().setColor(BLACK);
                parent.setColor(BLACK);
                leftRotate(parent);
                replaceNode = root;
            } else {
                // 替代节点为父节点的右子节点 和上面对称操作
                RBNode<T> brother = parent.getLeft();
                if (null != brother && RED == brother.isColor()) {
                    brother.setColor(BLACK);
                    parent.setColor(RED);
                    rightRotate(parent);
                    brother = parent.getLeft();
                }
                if (null == brother || (isBlack(brother.getLeft()) && isBlack(brother.getRight()))) {
                    if (null != brother) {
                        brother.setColor(RED);
                    }
                    replaceNode = parent;
                    parent = parent.getParent();
                    continue;
                }
                if (isRed(brother.getRight())) {
                    brother.setColor(BLACK);
                    brother.getRight().setColor(BLACK);
                    rightRotate(brother);
                    brother = brother.getParent();
                }
                brother.setColor(parent.isColor());
                parent.setColor(BLACK);
                brother.getLeft().setColor(BLACK);
                rightRotate(parent);
                replaceNode = root;
            }

        }
        if (replaceNode != null) {
            replaceNode.setColor(BLACK);
        }
    }

    public RBNode<T> search(T key) {
        return search(root, key);
    }

    /**
     * 查找"红黑树x"中键值为key的节点(递归实现)
     *
     * @param node node
     * @param key  key
     * @return RBNode
     */
    private RBNode<T> search(RBNode<T> node, T key) {
        if (null == node) {
            return null;
        }
        int flag = key.compareTo(node.getKey());
        if (flag < 0) {
            return search(node.getLeft(), key);
        } else if (flag > 0) {
            return search(node.getRight(), key);
        } else {
            return node;
        }
    }


    /**
     * 中序遍历
     *
     * @param root root
     */
    public void infix(RBNode<T> root) {
        if (null == root) {
            return;
        }
        if (null != root.getLeft()) {
            infix(root.getLeft());
        }
        System.out.println(root);
        if (null != root.getRight()) {
            infix(root.getRight());
        }
    }

    /**
     * 对目标节点进行左旋操作
     *
     * @param targetNode 目标节点
     */
    private void leftRotate(RBNode<T> targetNode) {
        // 目标节点的右子节点,下面称右儿子
        RBNode<T> targetRightSon = targetNode.getRight();
        // 将目标节点的右子节点设置为右儿子的左子节点
        targetNode.setRight(targetRightSon.getLeft());
        // 如果右儿子的左子节点不为空,则需要将它的父节点设置为目标节点
        if (null != targetRightSon.getLeft()) {
            targetRightSon.getLeft().setParent(targetNode);
        }
        // 将右儿子的父节点设为目标节点的父节点
        targetRightSon.setParent(targetNode.getParent());
        // 如果目标节点的父节点为空,说明目标节点是父节点,左旋后父节点应该变为右儿子
        if (null == targetNode.getParent()) {
            root = targetRightSon;
        } else {
            // 如果目标节点不是父节点,需要判断目标节点为其父节点的左子节点还是右子节点,将右儿子替换进去
            if (targetNode.getParent().getLeft() == targetNode) {
                targetNode.getParent().setLeft(targetRightSon);
            } else {
                targetNode.getParent().setRight(targetRightSon);
            }
        }
        // 将右儿子的左子节点设置为目标节点
        targetRightSon.setLeft(targetNode);
        // 将目标节点的父节点设置为右儿子
        targetNode.setParent(targetRightSon);
    }


    /**
     * 对目标节点进行右旋操作
     *
     * @param targetNode 目标节点
     */
    private void rightRotate(RBNode<T> targetNode) {
        // 目标节点的左子节点,下面称左儿子
        RBNode<T> targetLeftSon = targetNode.getLeft();
        // 将目标节点的左子节点设置为左儿子的右子节点
        targetNode.setLeft(targetLeftSon.getRight());
        // 如果左儿子的右节点不为空,则需要将它的父节点设置为目标节点
        if (null != targetLeftSon.getRight()) {
            targetLeftSon.getRight().setParent(targetNode);
        }
        // 将左儿子的父节点设置为目标节点的父节点
        targetLeftSon.setParent(targetNode.getParent());
        // 如果目标节点的父节点为空,说明目标节点是根节点,右旋后左二子应该变为父节点
        if (null == targetNode.getParent()) {
            root = targetLeftSon;
        } else {
            // 如果目标节点不是父节点,需要判断目标节点为其父节点的左子节点还是右子节点,将右儿子替换进去
            if (targetNode.getParent().getLeft() == targetNode) {
                targetNode.getParent().setLeft(targetLeftSon);
            } else {
                targetNode.getParent().setRight(targetLeftSon);
            }
        }
        // 将左儿子的右子节点设置为目标节点
        targetLeftSon.setRight(targetNode);
        // 将目标节点的父节点设置为左儿子
        targetNode.setParent(targetLeftSon);
    }


    /**
     * 当前节点颜色是否为黑色
     */
    private boolean isBlack(RBNode<T> node) {
        if (node == null) {
            return true;
        }
        return node.isColor() == BLACK;
    }

    /**
     * 当前节点颜色是否为红色
     */
    private boolean isRed(RBNode<T> node) {
        if (node == null) {
            return false;
        }
        return node.isColor() == RED;
    }

    @Data
    public static class RBNode<T extends Comparable<T>> {
        // 颜色
        boolean color;
        // 值
        T key;
        // 左子节点
        RBNode<T> left;
        // 右子节点
        RBNode<T> right;
        // 父节点
        RBNode<T> parent;

        public RBNode(boolean color, T key, RBNode<T> left, RBNode<T> right, RBNode<T> parent) {
            this.color = color;
            this.key = key;
            this.left = left;
            this.right = right;
            this.parent = parent;
        }

        @Override
        public String toString() {
            String colorText = color ? "黑色" : "红色";
            return "RBNode{" +
                    "color=" + colorText +
                    ", key=" + key +
                    ", left=" + (left == null ? "" : left.getKey()) +
                    ", right=" + (right == null ? "" : right.getKey()) +
                    ", parent=" + (parent == null ? "" : parent.getKey()) +
                    '}';
        }
    }
}
举报

相关推荐

0 条评论