private void FixTreeOnDelete(TextAnchorNode node, TextAnchorNode parentNode)
{
Debug.Assert(node == null || node.parent == parentNode);
if (parentNode == null)
return;
// warning: node may be null
var sibling = Sibling(node, parentNode);
if (sibling.color == RED)
{
parentNode.color = RED;
sibling.color = BLACK;
if (node == parentNode.left)
{
RotateLeft(parentNode);
}
else
{
RotateRight(parentNode);
}
sibling = Sibling(node, parentNode); // update value of sibling after rotation
}
if (parentNode.color == BLACK
&& sibling.color == BLACK
&& GetColor(sibling.left) == BLACK
&& GetColor(sibling.right) == BLACK)
{
sibling.color = RED;
FixTreeOnDelete(parentNode, parentNode.parent);
return;
}
if (parentNode.color == RED
&& sibling.color == BLACK
&& GetColor(sibling.left) == BLACK
&& GetColor(sibling.right) == BLACK)
{
sibling.color = RED;
parentNode.color = BLACK;
return;
}
if (node == parentNode.left &&
sibling.color == BLACK &&
GetColor(sibling.left) == RED &&
GetColor(sibling.right) == BLACK)
{
sibling.color = RED;
sibling.left.color = BLACK;
RotateRight(sibling);
}
else if (node == parentNode.right &&
sibling.color == BLACK &&
GetColor(sibling.right) == RED &&
GetColor(sibling.left) == BLACK)
{
sibling.color = RED;
sibling.right.color = BLACK;
RotateLeft(sibling);
}
sibling = Sibling(node, parentNode); // update value of sibling after rotation
sibling.color = parentNode.color;
parentNode.color = BLACK;
if (node == parentNode.left)
{
if (sibling.right != null)
{
Debug.Assert(sibling.right.color == RED);
sibling.right.color = BLACK;
}
RotateLeft(parentNode);
}
else
{
if (sibling.left != null)
{
Debug.Assert(sibling.left.color == RED);
sibling.left.color = BLACK;
}
RotateRight(parentNode);
}
}