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;
        }
    
    
    
  • 相关阅读:
    二分图 洛谷P2055 [ZJOI2009]假期的宿舍
    并查集 洛谷P1640 [SCOI2010]连续攻击游戏
    贪心 洛谷P2870 Best Cow Line, Gold
    贪心 NOIP2013 积木大赛
    快速幂 NOIP2013 转圈游戏
    倍增LCA NOIP2013 货车运输
    树形DP 洛谷P2014 选课
    KMP UVA1328 Period
    动态规划入门 BZOJ 1270 雷涛的小猫
    KMP POJ 2752Seek the Name, Seek the Fame
  • 原文地址:https://www.cnblogs.com/june777/p/11726105.html
Copyright © 2011-2022 走看看