/// <summary> /// is node.left.key <= node.key <= node.right.key /// </summary> /// <param name="node"></param> /// <returns></returns> public bool IsTreeNode(RBTreeNode <K, V> node) { if (node == null) { return(true); } if (node.Left != null && node.Left.Key.CompareTo(node.Key) > 0) { return(false); } if (node.Right != null && node.Right.Key.CompareTo(node.Key) < 0) { return(false); } return(true); }
/// <summary> /// Red Black insert /// </summary> /// <param name="key"></param> /// <param name="val"></param> public void Insert(K key, V val) { RBTreeNode <K, V> node = null, inserted = new RBTreeNode <K, V>(key, val); count++; RBTreeNode <K, V> x = root; while (x != null) { node = x; node.Size++; if (key.CompareTo(x.Key) < 0) { x = x.Left; } else { x = x.Right; } } inserted.Parent = node; //first insert a node if (node == null) { root = inserted; } else if (inserted.Key.CompareTo(node.Key) < 0) { node.Left = inserted; } else { node.Right = inserted; } inserted.Left = inserted.Right = null; inserted.Color = Color.RED; inserted.Size = 1; //fix up the insert node, so red black tree reserve InsertFixup(inserted); }
/// <summary> /// When TRANSPLANT replaces the subtree rooted at node u with /// the subtree rooted at node v , node u’s parent becomes node v’s parent, and u’s parent ends up having v as its appropriate child. /// </summary> /// <param name="u"></param> /// <param name="v"></param> private void Transplant(RBTreeNode <K, V> u, RBTreeNode <K, V> v) { if (u.Parent == null) { root = v; } else if (u == u.Parent.Left) { u.Parent.Left = v; } else { u.Parent.Right = v; } if (v != null) { v.Parent = u.Parent; } }
/// <summary> /// select the ith smallest tree node in inorder tree walk sequence rooted at root. /// null if can't find one /// it runs at O(lgn) /// </summary> /// <param name="root"></param> /// <param name="i"></param> /// <returns></returns> private RBTreeNode <K, V> Select(RBTreeNode <K, V> root, int i) { if (root == null) { return(null); } int r = 1 + (root.Left == null ? 0 : root.Left.Size); if (i == r) { return(root); } else if (i < r) { return(Select(root.Left, i)); } else { return(Select(root.Right, i - r)); } }
/// <summary> /// find successor /// </summary> /// <param name="root"></param> /// <returns></returns> public Tuple <K, V> Successor(RBTreeNode <K, V> root) { if (root == null) { return(null); } if (root.Right != null) { return(Minimum(root.Right)); } RBTreeNode <K, V> node = root.Parent; while (node != null && root == node.Right) { root = node; node = node.Parent; } return(node == null ? null : new Tuple <K, V>(node.Key, node.Value)); }
/// <summary> /// find successor /// </summary> /// <param name="root"></param> /// <returns></returns> public RBTreeNode <K, V> Successor_(RBTreeNode <K, V> root) { if (root == null) { return(null); } if (root.Right != null) { return(Minimum_(root.Right)); } RBTreeNode <K, V> node = root.Parent; while (node != null && root == node.Right) { root = node; node = node.Parent; } return(node); }
/// <summary> /// find predecessor /// </summary> /// <param name="root"></param> /// <returns></returns> public Tuple <K, V> Predecessor(RBTreeNode <K, V> root) { if (root == null) { return(null); } if (root.Left != null) { return(Maximum(root.Left)); } RBTreeNode <K, V> node = root.Parent; while (node != null && root == node.Left) { root = node; node = node.Parent; } return(node == null ? null : new Tuple <K, V>(node.Key, node.Value)); }
/// <summary> /// find predecessor /// </summary> /// <param name="root"></param> /// <returns></returns> public RBTreeNode <K, V> Predecessor_(RBTreeNode <K, V> root) { if (root == null) { return(null); } if (root.Left != null) { return(Maximum_(root.Left)); } RBTreeNode <K, V> node = root.Parent; while (node != null && root == node.Left) { root = node; node = node.Parent; } return(node); }
private RBTreeNode <K, V> Search_(K key, RBTreeNode <K, V> root) { if (root == null) { return(null); } int i = root.Key.CompareTo(key); if (i == 0) { return(root); } else if (i > 0) { return(Search_(key, root.Left)); } else { return(Search_(key, root.Right)); } }
/// <summary> /// right rotate /// </summary> /// <param name="x">x must have left child</param> private void RightRotate(RBTreeNode <K, V> x) { if (x.Left == null) { return; } RBTreeNode <K, V> y = x.Left; x.Left = y.Right; if (y.Right != null) { y.Right.Parent = x; } y.Parent = x.Parent; if (x.Parent == null) { root = y; } else if (x == x.Parent.Left) { x.Parent.Left = y; } else { x.Parent.Right = y; } y.Right = x; x.Parent = y; y.Size = x.Size; x.Size = Size(x.Left) + Size(x.Right) + 1; }
private bool IsRed(RBTreeNode <K, V> rBTreeNode) { return(!IsBlack(rBTreeNode)); }
private bool IsBlack(RBTreeNode <K, V> rBTreeNode) { return(rBTreeNode == null || rBTreeNode.Color == Color.BLACK); }
/// <summary> /// x must have at most one child /// 1)if the root deleted, then a red (must be red or it have none children) child be new root /// 2)all x's path black height less 1 /// 3)the father and x node may be both red /// </summary> /// <param name="x"></param> /// <param name="parent"></param> private void DeleteFixUp(RBTreeNode <K, V> x, RBTreeNode <K, V> parent) { RBTreeNode <K, V> w = null; while (x != root && IsBlack(x)) { //if x is not root then the parent is not null // x is double black & x can be null if (x == parent.Left) { //since node x is double black, node w can not be null, because the number of blacks on simple path from x.p to the leaf w would be smaller than the the number on simple path from x.p to x. w = parent.Right; if (IsRed(w)) { w.Color = Color.BLACK; parent.Color = Color.RED; LeftRotate(parent); w = parent.Right; //w still can not be null here } if (w != null && IsBlack(w.Left) && IsBlack(w.Right)) { w.Color = Color.RED; x = parent; parent = parent.Parent; } else if (w != null) { if (IsBlack(w.Right)) { //w.left is red if (w.Left != null) { w.Left.Color = Color.BLACK; } w.Color = Color.RED; RightRotate(w); w = parent.Right; } if (w != null) { w.Color = parent.Color; parent.Color = Color.BLACK; if (w.Right != null) { w.Right.Color = Color.BLACK; } LeftRotate(parent); x = root; } } } else { w = parent.Left; if (IsRed(w)) { w.Color = Color.BLACK; parent.Color = Color.RED; RightRotate(parent); w = parent.Left; } if (w != null && IsBlack(w.Left) && IsBlack(w.Right)) { w.Color = Color.RED; x = parent; parent = parent.Parent; } else if (w != null) { if (IsBlack(w.Left)) { if (w.Right != null) { w.Right.Color = Color.BLACK; } w.Color = Color.RED; LeftRotate(w); w = parent.Left; } if (w != null) { w.Color = parent.Color; parent.Color = Color.BLACK; if (w.Left != null) { w.Left.Color = Color.BLACK; } RightRotate(parent); //Setting x to be the root causes the while loop to terminate when it tests the loop condition. x = root; } } } } //if x origin color is red,then color black, which add 1 black at the path if (x != null) { x.Color = Color.BLACK; } }
/// <summary> /// delete the node /// </summary> /// <param name="node"></param> public void Delete(RBTreeNode <K, V> node) { if (node == null) { return; } count--; //node x that moves into node y’s original position. //node y as the node either removed from the tree or moved within the tree. //parent is the path where size need to minus 1 RBTreeNode <K, V> y = node, x = null, parent = null; Color yOriginColor = y.Color; if (node.Left == null) { x = node.Right; parent = node.Parent; Transplant(node, node.Right); } else if (node.Right == null) { x = node.Left; parent = node.Parent; Transplant(node, node.Left); } else { y = Minimum_(node.Right); yOriginColor = y.Color; x = y.Right; if (y.Parent == node) { parent = y; y.Size = node.Size; } else { //the post one is not right the right one parent = y.Parent; y.Size = node.Size; Transplant(y, y.Right); //because the post one is not the right child, then node.right is not null y.Right = node.Right; y.Right.Parent = y; } Transplant(node, y); y.Left = node.Left; //node.left is not null y.Left.Parent = y; y.Color = node.Color; } RBTreeNode <K, V> pNode = parent; while (pNode != null) { pNode.Size--; pNode = pNode.Parent; } if (yOriginColor == Color.BLACK) { // x can be null. if y originColor red, no violation of rbt // node x moves into node y’s original position //we can sure here parent is the parent of x ,but because x can be null, we need to use parent as a parameter DeleteFixUp(x, parent); } //if yOriginColor is red, then x is null and y is leaf node }
/// <summary> /// find the number of nodes in the tree /// </summary> /// <param name="node"></param> /// <returns></returns> private int Size(RBTreeNode <K, V> node) { return(node == null ? 0 : node.Size); }