zoukankan      html  css  js  c++  java
  • TreeMap数据结构(jdk8)

    TreeMap使用了红黑树的结构,看下源码,记录用。

        public V put(K key, V value) {
            Entry<K,V> t = root;
            //初始化
            if (t == null) {
                //key为null会报错,因此是保证key非null
                compare(key, key); // 
                //K-V 放到root
                root = new Entry<>(key, value, null);
                //实体的数量
                size = 1;
                //操作数
                modCount++;
                return null;
            }
            //比较结果
            int cmp;
            // 父节点
            Entry<K,V> parent;
            Comparator<? super K> cpr = comparator;
            //从root开始,用key和节点的key进行比较,小的找左树,大的找右树,相同就赋值然后返回。当t==null时,parent就是该节点父节点
            //使用自定义比较器
            if (cpr != null) {
                do {
                    parent = t;
                    cmp = cpr.compare(key, t.key);
                    if (cmp < 0)
                        t = t.left;
                    else if (cmp > 0)
                        t = t.right;
                    else
                        return t.setValue(value);
                } while (t != null);
            }
            //使用key的默认比较器
            else {
                if (key == null)
                    throw new NullPointerException();
                @SuppressWarnings("unchecked")
                    Comparable<? super K> k = (Comparable<? super K>) key;
                do {
                    parent = t;
                    cmp = k.compareTo(t.key);
                    if (cmp < 0)
                        t = t.left;
                    else if (cmp > 0)
                        t = t.right;
                    else
                        return t.setValue(value);
                } while (t != null);
            }
            //新节点e
            Entry<K,V> e = new Entry<>(key, value, parent);
            // 小的放在左儿子
            if (cmp < 0)
                parent.left = e;
            //其它放右儿子
            else
                parent.right = e;
            //修复树的平衡
            fixAfterInsertion(e);
            size++;
            modCount++;
            return null;
        }
    
        private void fixAfterInsertion(Entry<K,V> x) {
            //根据RBTREE要求,新插入节点为红色
            x.color = RED;
            //该节点不为null,不是root,且父节点为RED时开始修复平衡
            while (x != null && x != root && x.parent.color == RED) {
                //x的爸爸是 爷爷的左儿子
                if (parentOf(x) == leftOf(parentOf(parentOf(x)))) {
                    // y是爷爷的右儿子
                    Entry<K,V> y = rightOf(parentOf(parentOf(x)));
                    //如果y是红色的
                    if (colorOf(y) == RED) {
                        //把爷爷的左儿子置为黑色
                        setColor(parentOf(x), BLACK);
                        //把爷爷的右儿子置为黑色
                        setColor(y, BLACK);
                        //把爷爷置为黑色
                        setColor(parentOf(parentOf(x)), RED);
                        //把x变为爷爷
                        x = parentOf(parentOf(x));
                    //y是黑色的
                    } else {
                        //如果x是爸爸的右儿子
                        if (x == rightOf(parentOf(x))) {
                            //x设为爸爸
                            x = parentOf(x);
                            //左旋X
                            rotateLeft(x);
                        }
                        //把x的父亲设为黑色
                        setColor(parentOf(x), BLACK);
                        //把x的爷爷设为红色
                        setColor(parentOf(parentOf(x)), RED);
                        //右旋x的爷爷
                        rotateRight(parentOf(parentOf(x)));
                    }
                //爸爸是爷爷的右儿子
                } else {
                    //y是爷爷的左儿子
                    Entry<K,V> y = leftOf(parentOf(parentOf(x)));
                    //y是红色
                    if (colorOf(y) == RED) {
                        //x的父亲设为黑色
                        setColor(parentOf(x), BLACK);
                        //y设为黑色
                        setColor(y, BLACK);
                        //爷爷设为红色
                        setColor(parentOf(parentOf(x)), RED);
                        //x变为爷爷
                        x = parentOf(parentOf(x));
                    //y是黑色
                    } else {
                        //如果x是父亲的左儿子
                        if (x == leftOf(parentOf(x))) {
                            //x变为父亲
                            x = parentOf(x);
                            //右旋x
                            rotateRight(x);
                        }
                        //设置x父亲颜色为黑色
                        setColor(parentOf(x), BLACK);
                        //爷爷为红色
                        setColor(parentOf(parentOf(x)), RED);
                        //左旋爷爷
                        rotateLeft(parentOf(parentOf(x)));
                    }
                }
            }
            //根永远是黑色
            root.color = BLACK;
        }
    
    
    
  • 相关阅读:
    [慢查优化]慎用MySQL子查询,尤其是看到DEPENDENT SUBQUERY标记时
    Web开发基本准则-55实录-缓存策略
    Web开发基本准则-55实录-Web访问安全
    线上Java应用排查和诊断规范
    [慢查优化]建索引时注意字段选择性 & 范围查询注意组合索引的字段顺序
    [慢查优化]联表查询注意谁是驱动表 & 你搞不清楚谁join谁更好时请放手让mysql自行判定
    再说memcache的multiget hole(无底洞)
    RCA:未注意Curl-library Post 1024以上字节时的HTTP/1.1特性导致 HessianPHP 传输数据失败
    (研发系)职业化7个细节
    5·12和6·17两知名网站域名被劫持事件实施过程回放
  • 原文地址:https://www.cnblogs.com/june777/p/11726105.html
Copyright © 2011-2022 走看看