Java中的TreeMap與紅黑樹
文章目錄
TreeMap的有序指的是什麼?怎麼實現有序?用的什麼資料結構?
TreeMap是通過Key 的排序結果來實現有序的。TreeMap是通過Comparable或者Comparator來實現Key 的去重的,而不是通過hashCode和equals方法來比較,此處與HashMap和HashSet不同。因為要實現有序,所以key不能為null,但是value可以為null。
TreeMap的有序通過紅黑樹來保證。put方法分是否有comparator兩種情形考慮。如果有comparator,呼叫compare函式比較,找到插入位置。如果沒有comparator,呼叫自然排序的compareTo函式比較,找到插入位置。
以上兩種情形如果插入位置已有值(即key的比較結果為0),則直接覆蓋value。
如果插入位置無值,則按key大小放入插入位置的左結點或右結點,再呼叫fixAfterInsertion(e)來進行紅黑樹的著色和旋轉,完成後size++,modCount++。
public V put(K key, V value) {
Entry<K,V> t = root;
if (t == null) {
compare(key, key); // type (and possibly null) check
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 {
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);
}
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);
}
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;
}
為什麼說紅黑樹是AVL?
AVL樹(以發明者的名字命名)是自平衡二叉查詢樹,任何節點的兩個子樹的高度最大差別為1,因此不會像不平衡的二叉樹退化為連結串列,增加和刪除都是通過旋轉來達到平衡。AVL樹的高度<=log2(n+1).
紅黑樹並不是嚴格的AVL樹。紅黑樹保證每個節點到其可達葉子節點的所有路徑包含相同數目的黑色節點,根結點和虛結點NIL節點都是黑色,且不能有相鄰的兩個紅色結點。紅黑樹的新增、刪除、查詢的最壞時間複雜對為O(logn)。
下面看下紅黑樹的高度範圍。如果都去掉紅色節點,則高度<=log2(n+1),由於紅色節點不能相鄰,恢復紅色節點後,高度<=2log2(n+1)。比起AVL來說,高度粗略計算是2倍以內的,也是O(log2n)
紅黑樹怎麼維持平衡?
通過重新著色和左右旋轉實現平衡。
插入和刪除哪個簡單?
插入操作更簡單,刪除操作考慮的情形更多。
還有哪些集合使用紅黑樹?
HashMap、TreeSet、ConcurrentHashMap。