TreeMap继承关系,和HashMap同继承于AbstractMap,属于兄弟关系。
public class TreeMap<K,V> extends AbstractMap<K,V> implements NavigableMap<K,V>, Cloneable, java.io.Serializable
-1. 基于 NavigableMap 实现的红黑树
-2. 按 natrual ordering(Comparator==null,默认) 或者 Comparator 定义的次序排序
-3. 基本操作containsKey,get,put 有 log(n) 的时间复杂度
-4. 非线程安全
同步:SortedMap m = Collections.synchronizedSortedMap(new TreeMap(…));
红黑树节点类型,默认为黑
static final class Entry<K,V> implements Map.Entry<K,V> { K key; V value; Entry<K,V> left = null; Entry<K,V> right = null; Entry<K,V> parent; boolean color = BLACK; ... }
containsKey方法:
public boolean containsKey(Object key) { return getEntry(key) != null; }
final Entry<K,V> getEntry(Object key) { // Offload comparator-based version for sake of performance if (comparator != null) return getEntryUsingComparator(key); if (key == null) throw new NullPointerException(); Comparable<? super K> k = (Comparable<? super K>) key; Entry<K,V> p = root; //与二叉查找树的查找方式类似 while (p != null) { int cmp = k.compareTo(p.key); if (cmp < 0) p = p.left; else if (cmp > 0) p = p.right; else return p; } return null; }
containsValue方法:
public boolean containsValue(Object value) { for (Entry<K,V> e = getFirstEntry(); e != null; e = successor(e)) if (valEquals(value, e.value)) return true; return false; }
找到了树中最左边的结点,如果左子树中的值小于右子树,这就意味是第一个比较的结点是最小的结点
final Entry<K,V> getFirstEntry() { Entry<K,V> p = root; if (p != null) while (p.left != null) p = p.left; return p; }
successor 其实就是一个结点的下一个结点,所谓下一个,是按次序排序后的下一个结点。从代码中可以看出,如果右子树不为空,就返回右子树中最小结点。如果右子树为空,就要向上回溯了
static <K,V> TreeMap.Entry<K,V> successor(Entry<K,V> t) { if (t == null) return null; else if (t.right != null) { Entry<K,V> p = t.right; while (p.left != null) p = p.left; return p; } else { Entry<K,V> p = t.parent; Entry<K,V> ch = t; while (p != null && ch == p.right) { ch = p; p = p.parent; } return p; } }
final Entry<K,V> getCeilingEntry(K key):找一个 x.key >= key 的元素,并且 x是满足条件的元素中最小的。
public V put(K key, V value):如果树是空的,那么创建根结点。否则就要在树中插入结点如果 key 在树中,就 setValue 设置新值,否则,插入新结点。插入后调用fixAfterInsertion调整平衡性。
TreeMap 删除节点用被删除节点的右子树中最小节点与被删节点交换的方式进行维护。
红黑树(Red Black Tree) 是一种自平衡二叉查找树,是在计算机科学中用到的一种数据结构,典型的用途是实现关联数组。
性质1. 节点是红色或黑色。
性质2. 根节点是黑色。
性质3. 每个叶节点(NIL节点,空节点)是黑色的。
性质4. 每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点)。
性质5. 从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。
从根节点到叶子节点的路径中包含的黑色节点数被称为树的“黑色高度(black-height)”。
红黑树中最长路径就是一条红黑交替的路径。
黑色高度为 N 的红黑树,从根到叶子节点的最短路径长度为 N-1,最长路径长度为 2 * (N-1)。
红黑树并不是真正的平衡二叉树,但在实际应用中,红黑树的统计性能要高于平衡二叉树,但极端性能略差。
但是在Java 实现的红黑树将使用 null 来代表空节点,因此遍历红黑树时将看不到黑色的叶子节点,反而看到每个叶子节点都是红色的