zoukankan      html  css  js  c++  java
  • 一颗红黑树的实现

    大佬博客: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();
        }
    }
    
    
  • 相关阅读:
    Druid 介绍及配置
    LoadRunner性能测试入门教程
    Java 程序员必须收藏的资源大全
    JProfiler 入门教程
    Web网站的性能测试工具
    职场中必须知道的8条规则
    作为测试人员需要的技能和工作要求
    web性能监控与分析
    Java应用常用性能分析工具
    mockito简单教程
  • 原文地址:https://www.cnblogs.com/ZGQblogs/p/12514738.html
Copyright © 2011-2022 走看看