using System; using System.Collections.Generic; using System.Text; namespace QiHe.CodeLib { /// ///A red-black tree must satisfy these properties: ///1. The root is black. ///2. All leaves are black. ///3. Red nodes can only have black children. ///4. All paths from a node to its leaves contain the same number of black nodes. /// public class RedBlackTree : BinarySearchTreeBase> where TItem : IComparable { public override RedBlackTreeNode Nil { get { return RedBlackTreeNode.Nil; } } public override void Insert(RedBlackTreeNode node) { base.Insert(node); node.Color = NodeColor.Red; FixupAfterInsert(node); } /// /// restores the red-black properties to the search tree /// /// private void FixupAfterInsert(RedBlackTreeNode node) { while (node.Parent.Color == NodeColor.Red) { if (node.Parent.IsLeftChild) { RedBlackTreeNode uncle = node.Parent.Parent.Right; // case 1 if (uncle.Color == NodeColor.Red) { uncle.Color = NodeColor.Black; node.Parent.Color = NodeColor.Black; node.Parent.Parent.Color = NodeColor.Red; node = node.Parent.Parent; } else { // case 2 if (node.IsRightChild) { node = node.Parent; RotateLeft(node); } // case 3 node.Parent.Color = NodeColor.Black; node.Parent.Parent.Color = NodeColor.Red; RotateRight(node.Parent.Parent); } } else // "right" and "left" exchanged { RedBlackTreeNode uncle = node.Parent.Parent.Left; // case 1 if (uncle.Color == NodeColor.Red) { uncle.Color = NodeColor.Black; node.Parent.Color = NodeColor.Black; node.Parent.Parent.Color = NodeColor.Red; node = node.Parent.Parent; } else { // case 2 if (node.IsLeftChild) { node = node.Parent; RotateRight(node); } // case 3 node.Parent.Color = NodeColor.Black; node.Parent.Parent.Color = NodeColor.Red; RotateLeft(node.Parent.Parent); } } } Root.Color = NodeColor.Black; } public override RedBlackTreeNode Delete(RedBlackTreeNode node) { RedBlackTreeNode deletedNode = base.Delete(node); RedBlackTreeNode child = Nil; RedBlackTreeNode parent = deletedNode.Parent; if (parent != Nil) { child = deletedNode.IsLeftChild ? parent.Left : parent.Right; } if (deletedNode.Color == NodeColor.Black) { FixupAfterDelete(child); } return deletedNode; } /// /// restores the red-black properties to the search tree /// /// private void FixupAfterDelete(RedBlackTreeNode node) { while (node != Root && node.Color == NodeColor.Black) { if (node.IsLeftChild) { RedBlackTreeNode sibling = node.Parent.Right; if (sibling.Color == NodeColor.Red) { sibling.Color = NodeColor.Black; node.Parent.Color = NodeColor.Red; RotateLeft(node.Parent); sibling = node.Parent.Right; } if (sibling.Left.Color == NodeColor.Black && sibling.Right.Color == NodeColor.Black) { sibling.Color = NodeColor.Red; node = node.Parent; } else { if (sibling.Right.Color == NodeColor.Black) { sibling.Left.Color = NodeColor.Black; sibling.Color = NodeColor.Red; RotateRight(sibling); sibling = node.Parent.Right; } sibling.Color = node.Parent.Color; node.Parent.Color = NodeColor.Black; sibling.Right.Color = NodeColor.Black; RotateLeft(node.Parent); node = Root; } } else // same as code above with right and left swapped { RedBlackTreeNode sibling = node.Parent.Left; if (sibling.Color == NodeColor.Red) { sibling.Color = NodeColor.Black; node.Parent.Color = NodeColor.Red; RotateRight(node.Parent); sibling = node.Parent.Left; } if (sibling.Left.Color == NodeColor.Black && sibling.Right.Color == NodeColor.Black) { sibling.Color = NodeColor.Red; node = node.Parent; } else { if (sibling.Left.Color == NodeColor.Black) { sibling.Right.Color = NodeColor.Black; sibling.Color = NodeColor.Red; RotateLeft(sibling); sibling = node.Parent.Left; } sibling.Color = node.Parent.Color; node.Parent.Color = NodeColor.Black; sibling.Left.Color = NodeColor.Black; RotateRight(node.Parent); node = Root; } } } node.Color = NodeColor.Black; } } }