红黑树的插入

红黑树的性质不在多说,百度都有,今天来说说红黑的插入

红黑的插入分为三种情况,将其画了出来

这是第一种情况:

 

这是第二种情况

 

 第三种情况为

代码里有注释

enum Color{
    BLACK, RED
}

class RBNode<T extends Comparable<T>>{//创建红黑树的节点   值域、左孩子、右孩子、父亲,颜色
    private T data;
    private RBNode<T> left;
    private RBNode<T> right;
    private RBNode<T> parent;
    private Color color;
//  构造函数
    public RBNode(T data, RBNode<T> left, RBNode<T> right, RBNode<T> parent, Color color) {
        this.data = data;
        this.left = left;
        this.right = right;
        this.parent = parent;
        this.color = color;
    }

    public T getData() {
        return data;
    }

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

    public RBNode<T> getLeft() {
        return left;
    }

    public void setLeft(RBNode<T> left) {
        this.left = left;
    }

    public RBNode<T> getRight() {
        return right;
    }

    public void setRight(RBNode<T> right) {
        this.right = right;
    }

    public RBNode<T> getParent() {
        return parent;
    }

    public void setParent(RBNode<T> parent) {
        this.parent = parent;
    }

    public Color getColor() {
        return color;
    }

    public void setColor(Color color) {
        this.color = color;
    }
}

class RBTree<T extends Comparable<T>>{//创建红黑树
    private RBNode<T> root;//红黑树的根节点

    public RBTree() {
        this.root = null;
    }

    /**
     * 红黑树的插入
     * @param data
     */
    public void insert(T data){
        if (this.root == null){//如果这个红黑树上,没有节点就new一个新节点
            this.root = new RBNode<>(data,null,null,null,Color.BLACK);
            return;
        }
        RBNode<T> cur = this.root;//将根节点的地址给新创建的cur
        RBNode<T> parent = null;// 设置这节点的父节点
//        找节点插入的位置和BST树的查找插入位置一样
        while (cur != null){
            if (cur.getData().compareTo(data)>0){
                parent = cur;
                cur = cur.getLeft();
            }else if (cur.getData().compareTo(data)<0){
                parent = cur;
                cur = cur.getRight();
            }else {
                return;
            }
        }
//        红黑树的插入节点是红色
        RBNode<T> node = new RBNode<>(data,null,null,parent,Color.RED);
        if (parent.getData().compareTo(data)>0){
            parent.setLeft(node);//将此节点设置为父亲节点左边
        }else {
            parent.setRight(node);//将此节点设置为父亲节点的右边
        }

        if (color(parent(node)) == Color.RED){//如果插入的这个节点的父亲节点为红色 进入下面的颜色调整函数
            fixAfterInsert(node);
        }
    }

    /**
     * 颜色调整函数
     * @param node
     */
    private void fixAfterInsert(RBNode<T> node) {
        while(color(parent(node)) == Color.RED){//当插入的这个节点的父亲节点为红色进入这个循环
            if(left(parent(parent(node))) == parent(node)){
                // 当前节点,父节点在祖先节点的左子树
                RBNode<T> uncle = right(parent(parent(node)));//设置一个叔叔节点
                if(color(uncle) == Color.RED){ // 叔叔节点为红色 插入情况1
                    setColor(parent(node), Color.BLACK);//设置其节点的父亲节点为黑色
                    setColor(uncle, Color.BLACK);//设置其叔叔的节点为黑色
                    setColor(parent(parent(node)), Color.RED);//设置父亲的父亲为红色
                    node = parent(parent(node));//将node指向父亲的父亲
                } else {//叔叔节点不为红色 并且要插入的节点node在右子树上
                    if(node == right(parent(node))){ // 插入情况3前半段
                        node = parent(node);//设置要旋转的节点为node的父亲节点
                        leftRotate(node);//进行左旋
                    }
                    // 插入情况3后半段和情况2合并
                    setColor(parent(node), Color.BLACK);//设置节点的父亲节点为父亲节点
                    setColor(parent(parent(node)), Color.RED);//设置此节点的父亲的父亲为红色,进行右旋
                    rightRotate(parent(parent(node)));
                    break;
                }
            } else {
                // 当前节点,父节点在祖先节点的右树    和上面的一模一样
                RBNode<T> uncle = left(parent(parent(node)));
                if(color(uncle) == Color.RED){ // 插入情况1
                    setColor(parent(node), Color.BLACK);
                    setColor(uncle, Color.BLACK);
                    setColor(parent(parent(node)), Color.RED);
                    node = parent(parent(node));
                } else {
                    if(node == left(parent(node))){ // 插入情况3前半段
                        node = parent(node);
                        rightRotate(node);
                    }
                    setColor(parent(node), Color.BLACK); // 插入情况3后半段和情况2合并
                    setColor(parent(parent(node)), Color.RED);
                    leftRotate(parent(parent(node)));
                    break;
                }
            }
        }
        // 有可能向上回溯到根节点跳出,把根节点置成黑色
        setColor(this.root, Color.BLACK);
    }
    //左旋  这个旋转是基于BST树的旋转 这个要设置它的父亲和孩子进行绑定
    private void leftRotate(RBNode<T> node){
        RBNode<T> child = node.getRight();
        child.setParent(node.getParent());
        if(node.getParent() == null){
            this.root = child;
        } else {
            if(node.getParent().getLeft() == node){
                node.getParent().setLeft(child);
            } else {
                node.getParent().setRight(child);
            }
        }
        node.setRight(child.getLeft());
        if(child.getLeft() != null){
            child.getLeft().setParent(node);
        }

        child.setLeft(node);
        node.setParent(child);
    }
    //右旋
    private void rightRotate(RBNode<T> node){
        RBNode<T> child = node.getLeft();//定义要旋转的节点的左孩子
        child.setParent(node.getParent());//设置孩子的父亲
        if (node.getParent()==null){//如果要旋转的节点的父为null
            this.root = child;//将系统认定的根节点拉到child上
        }else {//判断要旋转的节点为他父节点的左边,设置为左边,或者设置为又变了
            if (node.getParent().getLeft()==node){
                node.getParent().setLeft(node);
            }else {
                node.getParent().setRight(node);
            }
        }
        node.setLeft(child.getRight());//将要旋转的节点的左边设置为孩子节点右节点
        if (child.getRight()!=null){//孩子的右孩子不为空,设置为它父节点
            child.getRight().setParent(node);
        }
        //将要旋转的节点设置为孩子节点的右孩子
        child.setRight(node);
        node.setParent(child);//设置要旋转的父亲为child
    }

    private Color color(RBNode<T> node){
        return node == null ? Color.BLACK : node.getColor();
    }

    public void setColor(RBNode<T> node, Color color){
        node.setColor(color);
    }

    public RBNode<T> left(RBNode<T> node){
        return node.getLeft();
    }

    public RBNode<T> right(RBNode<T> node){
        return node.getRight();
    }

    public RBNode<T> parent(RBNode<T> node){
        return node.getParent();
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值