一颗红黑树的实现

大佬博客:https://www.jianshu.com/p/e136ec79235c
这颗红黑树是我看了大佬博客的原理之后的手撸版本,代码实在是不够优雅.
这里只是留作纪念,相信等我看完HashMap源码以后一定会有不一样的感觉吧

经过测试,这颗红黑树复杂度还达不到完全的log,但是数量级是一样的.
在数据量为1e6时,log(1e6)应该是20,但是递归层数稳定在25左右
总的来说,差距不大
过一段时间把delete补上

package lab;
/**
 * @Author : ZGQ
 * @Date : 2020/3/17 15:58
 * @Version : 1.0
 */
public class RedBlackTree<V> {

    Node<V>root;

    public void put(Integer key,V value){
        if(root==null){
            root=new Node<>(key,value,null,null);
        }else{
            Node<V> tmp = add(root,key,value,null,null);
            if(tmp!=null){
                root=tmp;
            }
        }
        if(root.isRed){
            root.isRed=false;
        }

    }

//返回节点不为空表示现在还需要重新调整
    private Node<V> add(Node<V> present,Integer key, V value,Node<V> brother,Node<V> father) {

        //遇到值相同的,直接修改
        if(present.key.equals(key)){
            present.value= value;
            return null;
        }
        Node<V> son;
        boolean flag=present.isRed;
        if(key>present.key){
            if(present.right!=null){
                son = add(present.right,key,value,present.left,present);
                //如果下方修改过了,是要连续返回两次的
                //这里与写法有关
                //我的写法是,present在中间,father在上,son(新节点)在下
                //进行变化后,present或者son将取代father的位置
                //但是方法调用栈里面,father还是在上
                //所以这里需要连续返回两次
                //至于这个判断条件,是我观察得出的规律
                //满足这个规律,说明自己原来的儿子(或孙子)已经当自己的爸爸了
                if(present.isRed!=flag){
                    return son;
                }
                //儿子为空表示没有修改,不为空就赋值
                //注意,我们假设以刚刚发生修改的位置作为参考
                //这里已经连续返回两次,是爷爷了,
                if(son!=null){
                    present.right=son;
                }
            }else{
                //找到底了,直接加
                son = new Node<>(key,value,null,null);
                present.right=son;
            }
        }else{
            if(present.left!=null){
                son = add(present.left,key,value,present.right,present);
                if(present.isRed!=flag){
                    return son;
                }
                if(son!=null){
                    present.left=son;
                }
            }else{
                son = new Node<>(key,value,null,null);
                present.left=son;
            }
        }


        //下方没有修改或者当前节点是黑色
        if(son==null||!present.isRed||!son.isRed){
            return null;
        }


        //修改部分看大佬博客的原理,应该不难理解
        //就是这代码实在是不够优雅
        if(brother!=null&&brother.isRed){
            present.isRed=false;
            brother.isRed=false;
            father.isRed = true;
            return father;
        }


        if(father.left==present){
            if(present.left==son){

                present.isRed=true;
                father.isRed=true;

                father.left=present.right;
                present.right=father;

                return present;
            }else{
                son.isRed=false;
                father.isRed=false;

                son.left=present;
                son.right=father;
                father.left=null;
                present.right=null;

                return son;
            }
        }else{

            if(present.right==son){

                father.isRed=true;
                present.isRed=false;

                father.right=present.left;
                present.left=father;

                return present;

            }else{

                father.isRed=true;
                son.isRed=false;

                son.left=father;
                son.right=present;
                father.right=null;
                father.left=null;

                return son;
            }
        }
    }

    //查找就是和普通的二叉树一样了
    private V query(Node<V> root,Integer key){
        if(root==null){
            return null;
        }if(root.key.equals(key)){
            return root.value;
        }
        if(key>root.key){
            return query(root.right,key);
        }else{
            return query(root.left,key);
        }
    }

    public V get(Integer key){
        return query(root,key);
    }

    static class Node<V> {
        Integer key;
        V value;
        RedBlackTree.Node<V> left;
        RedBlackTree.Node<V> right;
        boolean isRed;

        Node(Integer key, V value, RedBlackTree.Node<V> left,RedBlackTree.Node<V> right) {
            this.key = key;
            this.value = value;
            this.left=left;
            this.right=right;
            isRed=true;
        }

        public final Integer getKey()        { return key; }
        public final V getValue()      { return value; }
        public final String toString() { return key + "=" + value; }

        public final V setValue(V newValue) {
            V oldValue = value;
            value = newValue;
            return oldValue;
        }

    }

    private void viewEndWithNull(Node<V> root){
        if(root==null){
            System.out.print("null ");
            return;
        }
        if(root.isRed){
            System.out.print(root.key+"| ");
        }
        else System.out.print(root.key+" ");
        viewEndWithNull(root.left);
        viewEndWithNull(root.right);
    }

    public void view(){
        viewEndWithNull(root);
        System.out.println();
    }
}

posted @ 2020-03-17 23:59  断腿三郎  阅读(229)  评论(0编辑  收藏  举报