/// <summary> /// Does a rotation on this tree. May change the color of a grandchild from red to black. /// </summary> public Node <T>?Rotate(TreeRotation rotation) { Node <T> removeRed; switch (rotation) { case TreeRotation.Right: removeRed = Left !.Left !; Debug.Assert(removeRed.IsRed); removeRed.ColorBlack(); return(RotateRight()); case TreeRotation.Left: removeRed = Right !.Right !; Debug.Assert(removeRed.IsRed); removeRed.ColorBlack(); return(RotateLeft()); case TreeRotation.RightLeft: Debug.Assert(Right !.Left !.IsRed); return(RotateRightLeft()); case TreeRotation.LeftRight: Debug.Assert(Left !.Right !.IsRed); return(RotateLeftRight()); default: Debug.Fail($"{nameof(rotation)}: {rotation} is not a defined {nameof(TreeRotation)} value."); return(null); } }
public bool Remove(T item) { if (Root == null) { return(false); } Node r = Root; Node parent = null; Node node3 = null; Node match = null; Node parentOfMatch = null; bool flag = false; while (r != null) { if (Is2Node(r)) { if (parent == null) { r.IsRed = true; } else { Node sibling = GetSibling(r, parent); if (sibling.IsRed) { if (parent.Right == sibling) { RotateLeft(parent); } else { RotateRight(parent); } parent.IsRed = true; sibling.IsRed = false; ReplaceChildOfNodeOrRoot(node3, parent, sibling); node3 = sibling; if (parent == match) { parentOfMatch = sibling; } sibling = (parent.Left == r) ? parent.Right : parent.Left; } if (Is2Node(sibling)) { Merge2Nodes(parent, r, sibling); } else { TreeRotation rotation = RotationNeeded(parent, r, sibling); Node newChild = null; switch (rotation) { case TreeRotation.LeftRotation: sibling.Right.IsRed = false; newChild = RotateLeft(parent); break; case TreeRotation.RightRotation: sibling.Left.IsRed = false; newChild = RotateRight(parent); break; case TreeRotation.RightLeftRotation: newChild = RotateRightLeft(parent); break; case TreeRotation.LeftRightRotation: newChild = RotateLeftRight(parent); break; } newChild.IsRed = parent.IsRed; parent.IsRed = false; r.IsRed = true; ReplaceChildOfNodeOrRoot(node3, parent, newChild); if (parent == match) { parentOfMatch = newChild; } node3 = newChild; } } } int num = flag ? -1 : comparer.Compare(item, r.Item); if (num == 0) { flag = true; match = r; parentOfMatch = parent; } node3 = parent; parent = r; if (num < 0) { r = r.Left; } else { r = r.Right; } } if (match != null) { ReplaceNode(match, parentOfMatch, parent, node3); count--; } if (this.Root != null) { this.Root.IsRed = false; } version++; return(flag); }
/// <summary> /// Removes the member. /// </summary> /// <param name="item">The item.</param> /// <returns></returns> private bool RemoveMember(T item) { if (_root == null) { return(false); } ++Version; Node node1 = _root; Node node2 = null; Node node3 = null; Node match = null; Node parentOfMatch = null; bool flag = false; while (node1 != null) { if (Is2Node(node1)) { if (node2 == null) { node1.IsRed = true; } else { Node node4 = GetSibling(node1, node2); if (node4.IsRed) { if (node2.Right == node4) { RotateLeft(node2); } else { RotateRight(node2); } node2.IsRed = true; node4.IsRed = false; ReplaceChildOfNodeOrRoot(node3, node2, node4); node3 = node4; if (node2 == match) { parentOfMatch = node4; } node4 = node2.Left == node1 ? node2.Right : node2.Left; } if (Is2Node(node4)) { Merge2Nodes(node2, node1, node4); } else { TreeRotation treeRotation = RotationNeeded(node2, node1, node4); Node newChild = null; switch (treeRotation) { case TreeRotation.LeftRotation: node4.Right.IsRed = false; newChild = RotateLeft(node2); break; case TreeRotation.RightRotation: node4.Left.IsRed = false; newChild = RotateRight(node2); break; case TreeRotation.RightLeftRotation: newChild = RotateRightLeft(node2); break; case TreeRotation.LeftRightRotation: newChild = RotateLeftRight(node2); break; } newChild.IsRed = node2.IsRed; node2.IsRed = false; node1.IsRed = true; ReplaceChildOfNodeOrRoot(node3, node2, newChild); if (node2 == match) { parentOfMatch = newChild; } } } } var comparer = flag ? -1 : _comparer.Compare(item, node1.Item); if (comparer == 0) { flag = true; match = node1; parentOfMatch = node2; } node3 = node2; node2 = node1; node1 = comparer >= 0 ? node1.Right : node1.Left; } if (match != null) { ReplaceNode(match, parentOfMatch, node2, node3); --Count; } if (_root != null) { _root.IsRed = false; } return(flag); }
internal virtual bool DoRemove(T item) { if (_root == null) { return(false); } // Search for a node and then find its succesor. // Then copy the item from the succesor to the matching node and delete the successor. // If a node doesn't have a successor, we can replace it with its left child (if not empty.) // or delete the matching node. // // In top-down implementation, it is important to make sure the node to be deleted is not a 2-node. // Following code will make sure the node on the path is not a 2 Node. // // Even if we don't actually remove from the set, we may be altering its structure (by doing rotations // and such). so update version to disable any enumerators/subsets working on it. // _version++; Node current = _root; Node parent = null; Node grandParent = null; Node match = null; Node parentOfMatch = null; bool foundMatch = false; while (current != null) { if (Is2Node(current)) { // fix up 2-Node if (parent == null) { // current is root. Mark it as red current.IsRed = true; } else { Node sibling = GetSibling(current, parent); if (sibling.IsRed) { // If parent is a 3-node, flip the orientation of the red link. // We can acheive this by a single rotation // This case is converted to one of other cased below. Debug.Assert(!parent.IsRed, "parent must be a black node!"); if (parent.Right == sibling) { RotateLeft(parent); } else { RotateRight(parent); } parent.IsRed = true; sibling.IsRed = false; // parent's color // sibling becomes child of grandParent or root after rotation. Update link from grandParent or root ReplaceChildOfNodeOrRoot(grandParent, parent, sibling); // sibling will become grandParent of current node grandParent = sibling; if (parent == match) { parentOfMatch = sibling; } // update sibling, this is necessary for following processing sibling = (parent.Left == current) ? parent.Right : parent.Left; } Debug.Assert(sibling != null || sibling.IsRed == false, "sibling must not be null and it must be black!"); if (Is2Node(sibling)) { Merge2Nodes(parent, current, sibling); } else { // current is a 2-node and sibling is either a 3-node or a 4-node. // We can change the color of current to red by some rotation. TreeRotation rotation = RotationNeeded(parent, current, sibling); Node newGrandParent = null; switch (rotation) { case TreeRotation.RightRotation: Debug.Assert(parent.Left == sibling, "sibling must be left child of parent!"); Debug.Assert(sibling.Left.IsRed, "Left child of sibling must be red!"); sibling.Left.IsRed = false; newGrandParent = RotateRight(parent); break; case TreeRotation.LeftRotation: Debug.Assert(parent.Right == sibling, "sibling must be left child of parent!"); Debug.Assert(sibling.Right.IsRed, "Right child of sibling must be red!"); sibling.Right.IsRed = false; newGrandParent = RotateLeft(parent); break; case TreeRotation.RightLeftRotation: Debug.Assert(parent.Right == sibling, "sibling must be left child of parent!"); Debug.Assert(sibling.Left.IsRed, "Left child of sibling must be red!"); newGrandParent = RotateRightLeft(parent); break; case TreeRotation.LeftRightRotation: Debug.Assert(parent.Left == sibling, "sibling must be left child of parent!"); Debug.Assert(sibling.Right.IsRed, "Right child of sibling must be red!"); newGrandParent = RotateLeftRight(parent); break; } newGrandParent.IsRed = parent.IsRed; parent.IsRed = false; current.IsRed = true; ReplaceChildOfNodeOrRoot(grandParent, parent, newGrandParent); if (parent == match) { parentOfMatch = newGrandParent; } grandParent = newGrandParent; } } } // we don't need to compare any more once we found the match int order = foundMatch ? -1 : _comparer.Compare(item, current.Item); if (order == 0) { // save the matching node foundMatch = true; match = current; parentOfMatch = parent; } grandParent = parent; parent = current; if (order < 0) { current = current.Left; } else { current = current.Right; // continue the search in right sub tree after we find a match } } // move successor to the matching node position and replace links if (match != null) { ReplaceNode(match, parentOfMatch, parent, grandParent); --_count; } if (_root != null) { _root.IsRed = false; } return(foundMatch); }
public bool Remove(Key key, Value value) { if (this.root == null) { return(false); } Node root = this.root; Node parent = null; Node node3 = null; Node match = null; Node parentOfMatch = null; bool flag = false; while (root != null) { if (Is2Node(root)) { if (parent == null) { root.IsRed = true; } else { Node sibling = GetSibling(root, parent); if (sibling.IsRed) { if (parent.Right == sibling) { RotateLeft(parent); } else { RotateRight(parent); } parent.IsRed = true; sibling.IsRed = false; this.ReplaceChildOfNodeOrRoot(node3, parent, sibling); node3 = sibling; if (parent == match) { parentOfMatch = sibling; } sibling = (parent.Left == root) ? parent.Right : parent.Left; } if (Is2Node(sibling)) { Merge2Nodes(parent, root, sibling); } else { TreeRotation rotation = RotationNeeded(parent, root, sibling); Node newChild = null; switch (rotation) { case TreeRotation.LeftRotation: sibling.Right.IsRed = false; newChild = RotateLeft(parent); break; case TreeRotation.RightRotation: sibling.Left.IsRed = false; newChild = RotateRight(parent); break; case TreeRotation.RightLeftRotation: newChild = RotateRightLeft(parent); break; case TreeRotation.LeftRightRotation: newChild = RotateLeftRight(parent); break; } newChild.IsRed = parent.IsRed; parent.IsRed = false; root.IsRed = true; this.ReplaceChildOfNodeOrRoot(node3, parent, newChild); if (parent == match) { parentOfMatch = newChild; } node3 = newChild; } } } int num = flag ? -1 : this.comparer.Compare(key, root.Key); if (num == 0) { flag = true; match = root; parentOfMatch = parent; } node3 = parent; parent = root; if (num < 0) { root = root.Left; } else { root = root.Right; } } if (match != null) { if (match.Values.Remove(value)) { this.count--; } if (match.Values.Count == 0) { this.ReplaceNode(match, parentOfMatch, parent, node3); } } if (this.root != null) { this.root.IsRed = false; } this.version++; return(flag); }
public bool Remove(T item) { if (this.root == null) { return(false); } TreeSet <T> .Node node = this.root; TreeSet <T> .Node node2 = null; TreeSet <T> .Node node3 = null; TreeSet <T> .Node node4 = null; TreeSet <T> .Node parentOfMatch = null; bool flag = false; while (node != null) { if (TreeSet <T> .Is2Node(node)) { if (node2 == null) { node.IsRed = true; } else { TreeSet <T> .Node node5 = TreeSet <T> .GetSibling(node, node2); if (node5.IsRed) { if (node2.Right == node5) { TreeSet <T> .RotateLeft(node2); } else { TreeSet <T> .RotateRight(node2); } node2.IsRed = true; node5.IsRed = false; this.ReplaceChildOfNodeOrRoot(node3, node2, node5); node3 = node5; if (node2 == node4) { parentOfMatch = node5; } node5 = ((node2.Left == node) ? node2.Right : node2.Left); } if (TreeSet <T> .Is2Node(node5)) { TreeSet <T> .Merge2Nodes(node2, node, node5); } else { TreeRotation treeRotation = TreeSet <T> .RotationNeeded(node2, node, node5); TreeSet <T> .Node node6 = null; switch (treeRotation) { case TreeRotation.LeftRotation: node5.Right.IsRed = false; node6 = TreeSet <T> .RotateLeft(node2); break; case TreeRotation.RightRotation: node5.Left.IsRed = false; node6 = TreeSet <T> .RotateRight(node2); break; case TreeRotation.RightLeftRotation: node6 = TreeSet <T> .RotateRightLeft(node2); break; case TreeRotation.LeftRightRotation: node6 = TreeSet <T> .RotateLeftRight(node2); break; } node6.IsRed = node2.IsRed; node2.IsRed = false; node.IsRed = true; this.ReplaceChildOfNodeOrRoot(node3, node2, node6); if (node2 == node4) { parentOfMatch = node6; } } } } int num = flag ? -1 : this.comparer.Compare(item, node.Item); if (num == 0) { flag = true; node4 = node; parentOfMatch = node2; } node3 = node2; node2 = node; if (num < 0) { node = node.Left; } else { node = node.Right; } } if (node4 != null) { this.ReplaceNode(node4, parentOfMatch, node2, node3); this.count--; } if (this.root != null) { this.root.IsRed = false; } this.version++; return(flag); }