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