TreeMap相关

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Map接口

Map集合的特点

1.能够存储唯一的列的数据(唯一,不可重复) Set

2.能够存储可以重复的数据(可重复) List

3.值的顺序取决于键的顺序

4.键和值都是可以存储null元素的

TreeMap

本质上就是红黑树的实现

1.每个节点要么是红色,要么是黑色。

2.根节点必须是黑色

3.每个叶子节点【NIL】是黑色

4.每个红色节点的两个子节点必须是黑色

5.任意节点到每个叶子节点的路径包含相同数量的黑节点

 K key; // key
V value; // 值
Entry<K,V> left; // 左子节点
Entry<K,V> right; // 右子节点
Entry<K,V> parent; // 父节点
boolean color = BLACK; // 节点的颜色 默认是黑色

 

put为例

    public V put(K key, V value) {
       // 将root赋值给局部变量 null
       Entry<K,V> t = root;
       if (t == null) {
           // 初始操作
           // 检查key是否为空
           compare(key, key); // type (and possibly null) check
// 将要添加的key、 value封装为一个Entry对象 并赋值给root
           root = new Entry<>(key, value, null);
           size = 1;
           modCount++;
           return null;
      }
       int cmp;
       Entry<K,V> parent; // 父节点
       // split comparator and comparable paths
       Comparator<? super K> cpr = comparator; // 获取比较器
       if (cpr != null) {
           // 一直找到插入节点的父节点
           do {
               // 将root赋值给了parent
               parent = t;
               // 和root节点比较值得大小
               cmp = cpr.compare(key, t.key);
               if (cmp < 0)
                   // 将父节点的左子节点付给了t
                   t = t.left;
               else if (cmp > 0)
                   t = t.right; // 将父节点的右节点付给了t
               else
                   // 直接和父节点的key相等,直接修改值
                   return t.setValue(value);
          } while (t != null);
      }

 

 


       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);
      }
       // t 就是我们要插入节点的父节点 parent
       // 将我们要插入的key value 封装成了一个Entry对象
       Entry<K,V> e = new Entry<>(key, value, parent);
       if (cmp < 0)
           parent.left = e; // 插入的节点在parent节点的左侧
       else
           parent.right = e; // 插入的节点在parent节点的右侧
       fixAfterInsertion(e); // 实现红黑树的平衡
       size++;
       modCount++;
       return null;
  }

 

 

/** From CLR */
private void fixAfterInsertion(Entry<K,V> x) {
// 设置添加节点的颜色为 红色
x.color = RED;
// 循环的条件 添加的节点不为空 不是root节点 父节点的颜色为红色
while (x != null && x != root && x.parent.color == RED) {
// 父节点是否是 祖父节点的左侧节点
if (parentOf(x) == leftOf(parentOf(parentOf(x)))) {
// 获取父节点的 兄弟节点 叔叔节点
Entry<K,V> y = rightOf(parentOf(parentOf(x)));
if (colorOf(y) == RED) { // 叔叔节点是红色
// 变色
setColor(parentOf(x), BLACK); // 设置 父节点的颜色为黑色
setColor(y, BLACK); // 设置叔叔节点的颜色为 黑色
setColor(parentOf(parentOf(x)), RED); // 设置 祖父节点的颜色是 红色
// 将祖父节点设置为 插入节点
x = parentOf(parentOf(x));
} else { // 叔叔节点是黑色
if (x == rightOf(parentOf(x))) {
// 判断插入节点是否是 父节点的右侧节点
x = parentOf(x); // 将父节点作为插入节点
rotateLeft(x); // 左旋
}
setColor(parentOf(x), BLACK);
setColor(parentOf(parentOf(x)), RED);
rotateRight(parentOf(parentOf(x)));// 右旋
}
} else {// 父节点是祖父节点的右侧子节点
// 获取叔叔节点
Entry<K,V> y = leftOf(parentOf(parentOf(x)));
if (colorOf(y) == RED) { // 叔叔节点为红色
// recolor 变色
setColor(parentOf(x), BLACK);
setColor(y, BLACK);
setColor(parentOf(parentOf(x)), RED);
x = parentOf(parentOf(x));
} else {
// 插入节点在父节点的右侧
if (x == leftOf(parentOf(x))) {
x = parentOf(x);
rotateRight(x); // 右旋
}
setColor(parentOf(x), BLACK);
setColor(parentOf(parentOf(x)), RED);
rotateLeft(parentOf(parentOf(x))); // 左旋
}
}
}
// 根节点的颜色为黑色
root.color = BLACK;
}

posted @ 2022-01-26 17:16  小白冲  阅读(201)  评论(0编辑  收藏  举报