private void balanceNode(RedBlackTreeNode <T> nodeToBalance) { //handle six cases while (nodeToBalance != null) { nodeToBalance.UpdateCounts(); nodeToBalance = handleDoubleBlack(nodeToBalance); } }
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); }