紅黑樹插入操作
阿新 • • 發佈:2019-01-05
/** From CLR */ private void rotateLeft(Entry<K,V> p) { if (p != null) { Entry<K,V> r = p.right; p.right = r.left; if (r.left != null) r.left.parent = p; r.parent = p.parent; if (p.parent == null) root = r; else if (p.parent.left == p) p.parent.left = r; else p.parent.right = r; r.left = p; p.parent = r; } } /** From CLR */ private void rotateRight(Entry<K,V> p) { if (p != null) { Entry<K,V> l = p.left; p.left = l.right; if (l.right != null) l.right.parent = p; l.parent = p.parent; if (p.parent == null) root = l; else if (p.parent.right == p) p.parent.right = l; else p.parent.left = l; l.right = p; p.parent = l; } }
分析: 左旋和右旋轉
/** From CLR */ private void fixAfterInsertion(Entry<K,V> x) { x.color = RED; 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) { 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; }
分析插入節點過程:
邏輯非常清楚,按照父節點(相對於x)是左節點還是有節點分兩大塊,這兩大塊操作對稱,下面就以父節點是左節點為例:
-
父節點P的兄弟節點為紅,那就讓你兩兄弟全變成黑,爺爺節點變紅,現在我們來看看以爺爺節點為根的這個子樹在經過變換後滿足黑平衡和性質4,接下來就是確認爺爺節點與在往上的節點有沒有衝突,也就是 x = parentOf(parentOf(x)),再while迴圈往上繼續檢查。
-
P的兄弟節點為黑,接下來分兩種:
1),N是左子節點,將其父節點改為黑,爺爺節點改為紅,右旋爺爺節點。看變換後左右的黑平衡都維持原樣。
2),N