예제 #1
0
 private bool IsNullOrBlack(RBNode <T> node)
 {
     return(node.IsNull() || !node.IsRed);
 }
예제 #2
0
        private void RemoveNode(RBNode <T> node)
        {
            RBNode <T> tmp = null; // after the below step, tmp points to the actual node to be deleted;

            if (node.Degree == 2)
            {
                tmp       = node.Left;
                path[++p] = tmp;
                while (tmp.Right != null)
                {
                    tmp       = tmp.Right;
                    path[++p] = tmp;
                }
                node.Item = tmp.Item;
            }
            else
            {
                tmp = node;
            }

            RBNode <T> newTmp = tmp.Left;

            if (newTmp.IsNull())
            {
                newTmp = tmp.Right;
            }

            if (p > 0)
            {
                RBNode <T> parent = path[p - 1];
                if (parent.Left == tmp)
                {
                    parent.Left = newTmp;
                }
                else
                {
                    parent.Right = newTmp;
                }

                // if the deleted is black and its single child is red.
                if (!tmp.IsRed && IsRed(newTmp))
                {
                    newTmp.IsRed = false;
                    return;
                }
            }
            else
            {
                // if delete the root node.
                _head = newTmp;
                if (_head.IsNotNull())
                {
                    _head.IsRed = false;
                }
                return;
            }

            path[p] = newTmp;
            if (IsRed(tmp))
            {
                // if the deleted is red, directly return.
                return;
            }

            // the deleted and its child are both BLACK.
            while (p > 0)
            {
                RBNode <T> current       = path[p];
                RBNode <T> parent        = path[p - 1];
                bool       currentIsLeft = (parent.Left == current);
                RBNode <T> sibling       = currentIsLeft ? parent.Right : parent.Left;
                if (IsRed(sibling))
                {
                    RBNode <T> newRoot;
                    if (currentIsLeft)
                    {
                        newRoot = RR(parent);
                    }
                    else
                    {
                        newRoot = LL(parent);
                    }
                    ReplaceChildOfNodeOrRoot(p > 1 ? path[p - 2] : null, parent, newRoot);
                    sibling.IsRed = false;
                    parent.IsRed  = true;

                    path[p - 1] = newRoot;
                    path[p]     = parent;
                    path[++p]   = current;
                }
                else
                {
                    // black sibling && black sibling-left && black sibling-right
                    if (IsNullOrBlack(sibling.Left) && IsNullOrBlack(sibling.Right))
                    {
                        if (parent.IsRed)
                        {
                            parent.IsRed  = false;
                            sibling.IsRed = true;
                            if (current.IsNotNull())
                            {
                                // TODO: not needed?
                                current.IsRed = false;
                            }
                            break;
                        }
                        else
                        {
                            // current must be black?
                            parent.IsRed = IsRed(current);
                            if (current.IsNotNull())
                            {
                                current.IsRed = false;
                            }
                            sibling.IsRed = true;
                            p--; // continue to backtrack.
                        }
                    }
                    else
                    {
                        RBNode <T> newRoot;
                        if (currentIsLeft)
                        {
                            if (IsRed(sibling.Right))
                            {
                                newRoot             = RR(parent);
                                sibling.Right.IsRed = false;
                            }
                            else
                            {
                                newRoot = RL(parent);
                            }
                        }
                        else
                        {
                            if (IsRed(sibling.Left))
                            {
                                newRoot            = LL(parent);
                                sibling.Left.IsRed = false;
                            }
                            else
                            {
                                newRoot = LR(parent);
                            }
                        }

                        if (current.IsNotNull())
                        {
                            current.IsRed = false;
                        }
                        newRoot.IsRed = parent.IsRed;
                        parent.IsRed  = false;
                        ReplaceChildOfNodeOrRoot(p > 1 ? path[p - 2] : null, parent, newRoot);
                        break;
                    }
                }
            }
        }