/// <summary> /// Checks if current node is in search range. /// </summary> private bool inRange(RedBlackTreeNode <RangeTreeNode <T> > currentNode, T start, T end) { //start is less than current and end is greater than current return(start.CompareTo(currentNode.Value.Value) <= 0 && end.CompareTo(currentNode.Value.Value) >= 0); }
private RedBlackTreeNode <T> findMax(RedBlackTreeNode <T> node) { return(node.FindMax() as RedBlackTreeNode <T>); }
internal RedBlackTreeNode(RedBlackTreeNode <T> parent, T value) { Parent = parent; Value = value; NodeColor = RedBlackTreeNodeColor.Red; }
/// <summary> /// Time complexity: O(1) /// </summary> internal void Clear() { Root = null; }
private RedBlackTreeNode <T> handleDoubleBlack(RedBlackTreeNode <T> node) { //case 1 if (node == Root) { node.NodeColor = RedBlackTreeNodeColor.Black; return(null); } //case 2 if (node.Parent != null && node.Parent.NodeColor == RedBlackTreeNodeColor.Black && node.Sibling != null && node.Sibling.NodeColor == RedBlackTreeNodeColor.Red && ((node.Sibling.Left == null && node.Sibling.Right == null) || (node.Sibling.Left != null && node.Sibling.Right != null && node.Sibling.Left.NodeColor == RedBlackTreeNodeColor.Black && node.Sibling.Right.NodeColor == RedBlackTreeNodeColor.Black))) { node.Parent.NodeColor = RedBlackTreeNodeColor.Red; node.Sibling.NodeColor = RedBlackTreeNodeColor.Black; if (node.Sibling.IsRightChild) { leftRotate(node.Parent); } else { rightRotate(node.Parent); } return(node); } //case 3 if (node.Parent != null && node.Parent.NodeColor == RedBlackTreeNodeColor.Black && node.Sibling != null && node.Sibling.NodeColor == RedBlackTreeNodeColor.Black && (node.Sibling.Left == null && node.Sibling.Right == null || node.Sibling.Left != null && node.Sibling.Right != null && node.Sibling.Left.NodeColor == RedBlackTreeNodeColor.Black && node.Sibling.Right.NodeColor == RedBlackTreeNodeColor.Black)) { //pushed up the double black problem up to parent //so now it needs to be fixed node.Sibling.NodeColor = RedBlackTreeNodeColor.Red; return(node.Parent); } //case 4 if (node.Parent != null && node.Parent.NodeColor == RedBlackTreeNodeColor.Red && node.Sibling != null && node.Sibling.NodeColor == RedBlackTreeNodeColor.Black && (node.Sibling.Left == null && node.Sibling.Right == null || node.Sibling.Left != null && node.Sibling.Right != null && node.Sibling.Left.NodeColor == RedBlackTreeNodeColor.Black && node.Sibling.Right.NodeColor == RedBlackTreeNodeColor.Black)) { //just swap the color of parent and sibling //which will compensate the loss of black count node.Parent.NodeColor = RedBlackTreeNodeColor.Black; node.Sibling.NodeColor = RedBlackTreeNodeColor.Red; node.UpdateCounts(true); return(null); } //case 5 if (node.Parent != null && node.Parent.NodeColor == RedBlackTreeNodeColor.Black && node.Sibling != null && node.Sibling.IsRightChild && node.Sibling.NodeColor == RedBlackTreeNodeColor.Black && node.Sibling.Left != null && node.Sibling.Left.NodeColor == RedBlackTreeNodeColor.Red && node.Sibling.Right != null && node.Sibling.Right.NodeColor == RedBlackTreeNodeColor.Black) { node.Sibling.NodeColor = RedBlackTreeNodeColor.Red; node.Sibling.Left.NodeColor = RedBlackTreeNodeColor.Black; rightRotate(node.Sibling); return(node); } //case 5 mirror if (node.Parent != null && node.Parent.NodeColor == RedBlackTreeNodeColor.Black && node.Sibling != null && node.Sibling.IsLeftChild && node.Sibling.NodeColor == RedBlackTreeNodeColor.Black && node.Sibling.Left != null && node.Sibling.Left.NodeColor == RedBlackTreeNodeColor.Black && node.Sibling.Right != null && node.Sibling.Right.NodeColor == RedBlackTreeNodeColor.Red) { node.Sibling.NodeColor = RedBlackTreeNodeColor.Red; node.Sibling.Right.NodeColor = RedBlackTreeNodeColor.Black; leftRotate(node.Sibling); return(node); } //case 6 if (node.Parent != null && node.Parent.NodeColor == RedBlackTreeNodeColor.Black && node.Sibling != null && node.Sibling.IsRightChild && node.Sibling.NodeColor == RedBlackTreeNodeColor.Black && node.Sibling.Right != null && node.Sibling.Right.NodeColor == RedBlackTreeNodeColor.Red) { //left rotate to increase the black count on left side by one //and mark the red right child of sibling to black //to compensate the loss of Black on right side of parent node.Sibling.Right.NodeColor = RedBlackTreeNodeColor.Black; leftRotate(node.Parent); node.UpdateCounts(true); return(null); } //case 6 mirror if (node.Parent != null && node.Parent.NodeColor == RedBlackTreeNodeColor.Black && node.Sibling != null && node.Sibling.IsLeftChild && node.Sibling.NodeColor == RedBlackTreeNodeColor.Black && node.Sibling.Left != null && node.Sibling.Left.NodeColor == RedBlackTreeNodeColor.Red) { //right rotate to increase the black count on right side by one //and mark the red left child of sibling to black //to compensate the loss of Black on right side of parent node.Sibling.Left.NodeColor = RedBlackTreeNodeColor.Black; rightRotate(node.Parent); node.UpdateCounts(true); return(null); } node.UpdateCounts(true); return(null); }
private void balanceInsertion(RedBlackTreeNode <T> nodeToBalance) { while (true) { if (nodeToBalance == Root) { nodeToBalance.NodeColor = RedBlackTreeNodeColor.Black; break; } //if node to balance is red if (nodeToBalance.NodeColor == RedBlackTreeNodeColor.Red) { //red-red relation; fix it! if (nodeToBalance.Parent.NodeColor == RedBlackTreeNodeColor.Red) { //red sibling if (nodeToBalance.Parent.Sibling != null && nodeToBalance.Parent.Sibling.NodeColor == RedBlackTreeNodeColor.Red) { //mark both children of parent as black and move up balancing nodeToBalance.Parent.Sibling.NodeColor = RedBlackTreeNodeColor.Black; nodeToBalance.Parent.NodeColor = RedBlackTreeNodeColor.Black; //root is always black if (nodeToBalance.Parent.Parent != Root) { nodeToBalance.Parent.Parent.NodeColor = RedBlackTreeNodeColor.Red; } nodeToBalance.UpdateCounts(); nodeToBalance.Parent.UpdateCounts(); nodeToBalance = nodeToBalance.Parent.Parent; } //absent sibling or black sibling else if (nodeToBalance.Parent.Sibling == null || nodeToBalance.Parent.Sibling.NodeColor == RedBlackTreeNodeColor.Black) { if (nodeToBalance.IsLeftChild && nodeToBalance.Parent.IsLeftChild) { var newRoot = nodeToBalance.Parent; swapColors(nodeToBalance.Parent, nodeToBalance.Parent.Parent); rightRotate(nodeToBalance.Parent.Parent); if (newRoot == Root) { Root.NodeColor = RedBlackTreeNodeColor.Black; } nodeToBalance.UpdateCounts(); nodeToBalance = newRoot; } else if (nodeToBalance.IsLeftChild && nodeToBalance.Parent.IsRightChild) { rightRotate(nodeToBalance.Parent); var newRoot = nodeToBalance; swapColors(nodeToBalance.Parent, nodeToBalance); leftRotate(nodeToBalance.Parent); if (newRoot == Root) { Root.NodeColor = RedBlackTreeNodeColor.Black; } nodeToBalance.UpdateCounts(); nodeToBalance = newRoot; } else if (nodeToBalance.IsRightChild && nodeToBalance.Parent.IsRightChild) { var newRoot = nodeToBalance.Parent; swapColors(nodeToBalance.Parent, nodeToBalance.Parent.Parent); leftRotate(nodeToBalance.Parent.Parent); if (newRoot == Root) { Root.NodeColor = RedBlackTreeNodeColor.Black; } nodeToBalance.UpdateCounts(); nodeToBalance = newRoot; } else if (nodeToBalance.IsRightChild && nodeToBalance.Parent.IsLeftChild) { leftRotate(nodeToBalance.Parent); var newRoot = nodeToBalance; swapColors(nodeToBalance.Parent, nodeToBalance); rightRotate(nodeToBalance.Parent); if (newRoot == Root) { Root.NodeColor = RedBlackTreeNodeColor.Black; } nodeToBalance.UpdateCounts(); nodeToBalance = newRoot; } } } } if (nodeToBalance.Parent != null) { nodeToBalance.UpdateCounts(); nodeToBalance = nodeToBalance.Parent; continue; } break; } nodeToBalance.UpdateCounts(true); }
//O(log(n)) always private void delete(RedBlackTreeNode <T> node, T value) { RedBlackTreeNode <T> nodeToBalance = null; var compareResult = node.Value.CompareTo(value); //node is less than the search value so move right to find the deletion node if (compareResult < 0) { if (node.Right == null) { throw new Exception("Item do not exist"); } delete(node.Right, value); } //node is less than the search value so move left to find the deletion node else if (compareResult > 0) { if (node.Left == null) { throw new Exception("Item do not exist"); } delete(node.Left, value); } else { //duplicate - easy fix if (node.Values.Count > 1) { node.Values.RemoveAt(node.Values.Count - 1); return; } //node is a leaf node if (node.IsLeaf) { //if color is red, we are good; no need to balance if (node.NodeColor == RedBlackTreeNodeColor.Red) { deleteLeaf(node); return; } nodeToBalance = handleDoubleBlack(node); deleteLeaf(node); } else { //case one - right tree is null (move sub tree up) if (node.Left != null && node.Right == null) { nodeToBalance = handleDoubleBlack(node); deleteLeftNode(node); } //case two - left tree is null (move sub tree up) else if (node.Right != null && node.Left == null) { nodeToBalance = handleDoubleBlack(node); deleteRightNode(node); } //case three - two child trees //replace the node value with maximum element of left subtree (left max node) //and then delete the left max node else { var maxLeftNode = FindMax(node.Left); node.Values.Clear(); node.Values.Add(maxLeftNode.Value); //delete left max node delete(node.Left, maxLeftNode.Value); } } } //handle six cases while (nodeToBalance != null) { nodeToBalance = handleDoubleBlack(nodeToBalance); } }
/// <summary> /// update max end value under each node in red-black tree recursively. /// </summary> private void updateMax(RedBlackTreeNode <OneDimentionalInterval <T> > node, T currentMax, bool recurseUp = true) { while (true) { if (node == null) { return; } if (node.Left != null && node.Right != null) { //if current Max is less than current End //then update current Max if (currentMax.CompareTo(node.Left.Value.MaxEnd) < 0) { currentMax = node.Left.Value.MaxEnd; } if (currentMax.CompareTo(node.Right.Value.MaxEnd) < 0) { currentMax = node.Right.Value.MaxEnd; } } else if (node.Left != null) { //if current Max is less than current End //then update current Max if (currentMax.CompareTo(node.Left.Value.MaxEnd) < 0) { currentMax = node.Left.Value.MaxEnd; } } else if (node.Right != null) { if (currentMax.CompareTo(node.Right.Value.MaxEnd) < 0) { currentMax = node.Right.Value.MaxEnd; } } foreach (var v in node.Value.End) { if (currentMax.CompareTo(v) < 0) { currentMax = v; } } node.Value.MaxEnd = currentMax; if (recurseUp) { node = node.Parent; continue; } break; } }