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;
}
}
}