简单易懂的红黑树代码—java

首先定义一颗树:

/**
 * 红黑树
 * @param <K>
 * @param <V>
 *
 *     红黑树的特性:
 *     1. 根节点必须是黑色
 *     2. 叶子节点(NIL)必须是黑色
 *     3. 从根节点到叶子节点的黑色节点的数量一致
 *     4. 不能有两个相邻的红色节点
 *     5. 红黑树要么是红色/要么是黑色
 *     6. 新增节点一般是红色 (为红色不一定会破坏红黑树的特性  为黑色则一定会破坏红黑数的特性)
 */
public class RBTree <K extends Comparable,V>{

    private Boolean BLACK=false;
    private Boolean RED=true;
    private RBNode root;  // 根节点
    static class RBNode<K extends Comparable,V>{
        private RBNode left;
        private RBNode right;
        private RBNode parent;
        private K key;
        private V value;
        private Boolean color;
    }

定义基础操作方法:

/**
     *  变色
     */
    private void setColor(RBNode node,Boolean color){

        if(node == null){
            return;
        }
        node.setColor(color);
    }

    /**
     * 获取父级节点
     * @param node
     * @return
     */
    private RBNode getParent(RBNode node){
        if(node == null){
            return null;
        }

        return node.getParent();
    }
/**
     * 是否是红色
     * @param node
     * @return
     */
    private Boolean isRed(RBNode node){
        if(node == null){
            return false;
        }
        return node.getColor()==RED;
    }
 /**
     * 中序遍历
     */
    public void print(){
        RBNode node = this.root;
        print(root);
        System.out.println("root: "+node.getKey());
    }

    private void print(RBNode root){
        if(root ==null){
            return ;
        }
        print(root.left);
        String color=root.getColor()?"红色":"黑色";
        System.out.println("key:  "+ root.getKey()+"   value: "+ root.getValue()+"   color:   "+ color);
        print(root.right);
    }

定义左旋右旋:
左旋: 将右子节点的左子节点变为右子节点,将原来的右子节点指向x的父级节点。
右旋:将左子节点的右子节点变为左子节点,将原来的左子节点指向x的父级节点

/**
     * 左旋
     * 1. 找到node节点的right节点,先将y的left节点变为x的right节点,不为空的话将parent指向x;
     * 2. 将y的父级指向x的父级   将x在父级的位置指向y
     */
    private void leftRotate(RBNode x){
        RBNode y = x.right;
        x.right = y.left;
        if(y.left !=null){
            y.left.parent = x;
        }
        // 获取x的父级节点  将y的父级指向x的父级节点
        RBNode parent = getParent(x);
        if(parent !=null){
            y.parent = parent;
            if(x == parent.left){
                parent.left = y;
            }else{
                parent.right = y;
            }
        }else{
            // 表示x是root节点  直接赋值y
            this.root = y;
            y.parent = null;
        }

        x.parent = y;
        y.left = x;
    }


    /**
     * 右旋
     * 1. 找到node节点的right节点,先将y的left节点变为x的right节点,不为空的话将parent指向x;
     * 2. 将y的父级指向x的父级   将x在父级的位置指向y
     */
    private void rightRotate(RBNode x){
        RBNode y = x.left;
        x.left = y.right;
        if(y.right !=null){
            y.right.parent = x;
        }
        // 获取x的父级节点  将y的父级指向x的父级节点
        RBNode parent = getParent(x);
        if(parent !=null){
            y.parent = parent;
            if(x == parent.left){
                parent.left = y;
            }else{
                parent.right = y;
            }
        }else{
            // 表示x是root节点  直接赋值y
            this.root = y;
            y.parent = null;
        }

        x.parent = y;
        y.right = x;
    }

定义插入,及插入后调整方法:

/**
     * 对外insert接口
     * @param key
     * @param value
     */
    public void insert(K key,V value){
        RBNode node = new RBNode<>();
        node.setColor(RED);
        node.setKey(key);
        node.setValue(value);
        insert(node);
    }

    /**
     * 插入元素   先找到parent
     * @param node
     */
    private void insert(RBNode node){
        RBNode parent= null;
        RBNode root = this.root;
        while(root !=null){
            parent = root;
            int tem = node.getKey().compareTo(root.getKey());
            if(tem > 0){
                root = root.right;
            }else if(tem == 0){
                root.setValue(node.getValue());
                return;
            }else{
                root = root.left;
            }
        }
        if(parent ==null){
            this.root = node;
        }else{
            node.setParent(parent);
            int tem = node.getKey().compareTo(parent.getKey());
            if(tem > 0){
                parent.right = node;
            }else{
                parent.left = node;
            }
        }
        ficUp(node);
    }

    /**
     *  调整符合红黑树特性的操作
     *  情况分为:
     *      1.root节点为空 ,插入后将root节点班委黑色。
     *      2. 插入节点的父级节点为黑色    不违反红黑树特性 不做调整
     *      3. 插入节点已存在   insert中已覆盖
     *      4.  插入节点的父级节点为红色:{
     *          1. 如果叔叔级节点为红色  为双红   将父级节点和叔叔级节点变为黑色,将爷爷级节点变为红色  以爷爷节点进行再次处理
     *          2. 如果叔叔级节点不存在或为黑色:{
     *              1. 父级节点在爷爷级节点的left,插入节点在父级节点的left  为(LL)双红  父级变为黑色,爷爷变为红色。 以爷爷节点进行右旋
     *              2. 插入节点在父级的右侧,为(LR) 双红, 以父级节点进行左旋  变为(LL双红)
     *              3. 父级节点在爷爷级节点的右侧,插入节点在父级节点的right 为(RR)双红  父级变为黑色,爷爷变为红色。 以爷爷节点进行左旋
     *              4. 插入节点在父级的左侧 为(RL)双红 , 以父级节点进行右旋  变为(RR)双红
     *         }
     *      }
     */
    private void ficUp(RBNode node){
        this.root.setColor(BLACK);
        RBNode parent = getParent(node);
        RBNode gParent = getParent(parent);
        if(parent !=null && isRed(parent)){
            RBNode uncle = null;
            if(gParent.left == parent){
                uncle = gParent.right;
            }else{
                uncle = gParent.left;
            }
            if(uncle != null && isRed(uncle)){
                parent.setColor(BLACK);
                uncle.setColor(BLACK);
                gParent.setColor(RED);
                ficUp(gParent);
                return;
            }else{
                if(parent == gParent.left){
                    if(parent.left == node){
                        parent.setColor(BLACK);
                        gParent.setColor(RED);
                        rightRotate(gParent);
                    }else{
                        leftRotate(parent);
                        ficUp(parent);
                        return;
                    }
                }else{
                    if(parent.left == node){
                        rightRotate(parent);
                        ficUp(parent);
                        return;

                    }else{
                        parent.setColor(BLACK);
                        gParent.setColor(RED);
                        leftRotate(gParent);
                    }
                }
            }
        }
    }

完整代码如下:



import com.sun.org.apache.xpath.internal.operations.Bool;

import java.util.Collections;
import java.util.TreeMap;

/**
 * 红黑树
 * @param <K>
 * @param <V>
 *
 *     红黑树的特性:
 *     1. 根节点必须是黑色
 *     2. 叶子节点(NIL)必须是黑色
 *     3. 从根节点到叶子节点的黑色节点的数量一致
 *     4. 不能有两个相邻的红色节点
 *     5. 红黑树要么是红色/要么是黑色
 *     6. 新增节点一般是红色 (为红色不一定会破坏红黑树的特性  为黑色则一定会破坏红黑数的特性)
 */
public class RBTree <K extends Comparable,V>{

    private Boolean BLACK=false;
    private Boolean RED=true;
    private RBNode root;  // 根节点
    static class RBNode<K extends Comparable,V>{
        private RBNode left;
        private RBNode right;
        private RBNode parent;
        private K key;
        private V value;
        private Boolean color;


        public RBNode getLeft() {
            return left;
        }

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

        public RBNode getRight() {
            return right;
        }

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

        public RBNode getParent() {
            return parent;
        }

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

        public K getKey() {
            return key;
        }

        public void setKey(K key) {
            this.key = key;
        }

        public V getValue() {
            return value;
        }

        public void setValue(V value) {
            this.value = value;
        }

        public Boolean getColor() {
            return color;
        }

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

        public RBNode() {
        }
    }
    /**
     *  变色
     */
    private void setColor(RBNode node,Boolean color){

        if(node == null){
            return;
        }
        node.setColor(color);
    }

    /**
     * 获取父级节点
     * @param node
     * @return
     */
    private RBNode getParent(RBNode node){
        if(node == null){
            return null;
        }

        return node.getParent();
    }

    /**
     * 左旋
     * 1. 找到node节点的right节点,先将y的left节点变为x的right节点,不为空的话将parent指向x;
     * 2. 将y的父级指向x的父级   将x在父级的位置指向y
     */
    private void leftRotate(RBNode x){
        RBNode y = x.right;
        x.right = y.left;
        if(y.left !=null){
            y.left.parent = x;
        }
        // 获取x的父级节点  将y的父级指向x的父级节点
        RBNode parent = getParent(x);
        if(parent !=null){
            y.parent = parent;
            if(x == parent.left){
                parent.left = y;
            }else{
                parent.right = y;
            }
        }else{
            // 表示x是root节点  直接赋值y
            this.root = y;
            y.parent = null;
        }

        x.parent = y;
        y.left = x;
    }


    /**
     * 右旋
     * 1. 找到node节点的right节点,先将y的left节点变为x的right节点,不为空的话将parent指向x;
     * 2. 将y的父级指向x的父级   将x在父级的位置指向y
     */
    private void rightRotate(RBNode x){
        RBNode y = x.left;
        x.left = y.right;
        if(y.right !=null){
            y.right.parent = x;
        }
        // 获取x的父级节点  将y的父级指向x的父级节点
        RBNode parent = getParent(x);
        if(parent !=null){
            y.parent = parent;
            if(x == parent.left){
                parent.left = y;
            }else{
                parent.right = y;
            }
        }else{
            // 表示x是root节点  直接赋值y
            this.root = y;
            y.parent = null;
        }

        x.parent = y;
        y.right = x;
    }

    /**
     * 是否是红色
     * @param node
     * @return
     */
    private Boolean isRed(RBNode node){
        if(node == null){
            return false;
        }
        return node.getColor()==RED;
    }

    /**
     * 对外insert接口
     * @param key
     * @param value
     */
    public void insert(K key,V value){
        RBNode node = new RBNode<>();
        node.setColor(RED);
        node.setKey(key);
        node.setValue(value);
        insert(node);
    }

    /**
     * 插入元素   先找到parent
     * @param node
     */
    private void insert(RBNode node){
        RBNode parent= null;
        RBNode root = this.root;
        while(root !=null){
            parent = root;
            int tem = node.getKey().compareTo(root.getKey());
            if(tem > 0){
                root = root.right;
            }else if(tem == 0){
                root.setValue(node.getValue());
                return;
            }else{
                root = root.left;
            }
        }
        if(parent ==null){
            this.root = node;
        }else{
            node.setParent(parent);
            int tem = node.getKey().compareTo(parent.getKey());
            if(tem > 0){
                parent.right = node;
            }else{
                parent.left = node;
            }
        }
        ficUp(node);
    }

    /**
     *  调整符合红黑树特性的操作
     *  情况分为:
     *      1.root节点为空 ,插入后将root节点班委黑色。
     *      2. 插入节点的父级节点为黑色    不违反红黑树特性 不做调整
     *      3. 插入节点已存在   insert中已覆盖
     *      4.  插入节点的父级节点为红色:{
     *          1. 如果叔叔级节点为红色  为双红   将父级节点和叔叔级节点变为黑色,将爷爷级节点变为红色  以爷爷节点进行再次处理
     *          2. 如果叔叔级节点不存在或为黑色:{
     *              1. 父级节点在爷爷级节点的left,插入节点在父级节点的left  为(LL)双红  父级变为黑色,爷爷变为红色。 以爷爷节点进行右旋
     *              2. 插入节点在父级的右侧,为(LR) 双红, 以父级节点进行左旋  变为(LL双红)
     *              3. 父级节点在爷爷级节点的右侧,插入节点在父级节点的right 为(RR)双红  父级变为黑色,爷爷变为红色。 以爷爷节点进行左旋
     *              4. 插入节点在父级的左侧 为(RL)双红 , 以父级节点进行右旋  变为(RR)双红
     *         }
     *      }
     */
    private void ficUp(RBNode node){
        this.root.setColor(BLACK);
        RBNode parent = getParent(node);
        RBNode gParent = getParent(parent);
        if(parent !=null && isRed(parent)){
            RBNode uncle = null;
            if(gParent.left == parent){
                uncle = gParent.right;
            }else{
                uncle = gParent.left;
            }
            if(uncle != null && isRed(uncle)){
                parent.setColor(BLACK);
                uncle.setColor(BLACK);
                gParent.setColor(RED);
                ficUp(gParent);
                return;
            }else{
                if(parent == gParent.left){
                    if(parent.left == node){
                        parent.setColor(BLACK);
                        gParent.setColor(RED);
                        rightRotate(gParent);
                    }else{
                        leftRotate(parent);
                        ficUp(parent);
                        return;
                    }
                }else{
                    if(parent.left == node){
                        rightRotate(parent);
                        ficUp(parent);
                        return;

                    }else{
                        parent.setColor(BLACK);
                        gParent.setColor(RED);
                        leftRotate(gParent);
                    }
                }
            }
        }
    }
    /**
     * 中序遍历
     */
    public void print(){
        RBNode node = this.root;
        print(root);
        System.out.println("root: "+node.getKey());
    }

    private void print(RBNode root){
        if(root ==null){
            return ;
        }
        print(root.left);
        String color=root.getColor()?"红色":"黑色";
        System.out.println("key:  "+ root.getKey()+"   value: "+ root.getValue()+"   color:   "+ color);
        print(root.right);
    }

    
}

编写Test 类进行测试:

public class RBTest {
    public static void main(String[] args) {
    //    int a[] = { 16, 88, 7, 11, 9, 26, 18, 14, 15 };
        int a[] = { 1,5,9,2,8,4,6,3,7,15};
        RBTree tree = new RBTree();
        for(int i = 0;i<a.length;i++){
            tree.insert(a[i],null);
        }
        tree.print();
    }
}

OK !

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值