예제 #1
0
        /// <summary>
        /// Does a rotation on this tree. May change the color of a grandchild from red to black.
        /// </summary>
        public Node <T>?Rotate(TreeRotation rotation)
        {
            Node <T> removeRed;

            switch (rotation)
            {
            case TreeRotation.Right:
                removeRed = Left !.Left !;
                Debug.Assert(removeRed.IsRed);
                removeRed.ColorBlack();
                return(RotateRight());

            case TreeRotation.Left:
                removeRed = Right !.Right !;
                Debug.Assert(removeRed.IsRed);
                removeRed.ColorBlack();
                return(RotateLeft());

            case TreeRotation.RightLeft:
                Debug.Assert(Right !.Left !.IsRed);
                return(RotateRightLeft());

            case TreeRotation.LeftRight:
                Debug.Assert(Left !.Right !.IsRed);
                return(RotateLeftRight());

            default:
                Debug.Fail($"{nameof(rotation)}: {rotation} is not a defined {nameof(TreeRotation)} value.");
                return(null);
            }
        }
예제 #2
0
파일: TreeSet.cs 프로젝트: obpositive/yal
        public bool Remove(T item)
        {
            if (Root == null)
            {
                return(false);
            }
            Node r             = Root;
            Node parent        = null;
            Node node3         = null;
            Node match         = null;
            Node parentOfMatch = null;
            bool flag          = false;

            while (r != null)
            {
                if (Is2Node(r))
                {
                    if (parent == null)
                    {
                        r.IsRed = true;
                    }
                    else
                    {
                        Node sibling = GetSibling(r, parent);
                        if (sibling.IsRed)
                        {
                            if (parent.Right == sibling)
                            {
                                RotateLeft(parent);
                            }
                            else
                            {
                                RotateRight(parent);
                            }
                            parent.IsRed  = true;
                            sibling.IsRed = false;
                            ReplaceChildOfNodeOrRoot(node3, parent, sibling);
                            node3 = sibling;
                            if (parent == match)
                            {
                                parentOfMatch = sibling;
                            }
                            sibling = (parent.Left == r) ? parent.Right : parent.Left;
                        }
                        if (Is2Node(sibling))
                        {
                            Merge2Nodes(parent, r, sibling);
                        }
                        else
                        {
                            TreeRotation rotation = RotationNeeded(parent, r, sibling);
                            Node         newChild = null;
                            switch (rotation)
                            {
                            case TreeRotation.LeftRotation:
                                sibling.Right.IsRed = false;
                                newChild            = RotateLeft(parent);
                                break;

                            case TreeRotation.RightRotation:
                                sibling.Left.IsRed = false;
                                newChild           = RotateRight(parent);
                                break;

                            case TreeRotation.RightLeftRotation:
                                newChild = RotateRightLeft(parent);
                                break;

                            case TreeRotation.LeftRightRotation:
                                newChild = RotateLeftRight(parent);
                                break;
                            }
                            newChild.IsRed = parent.IsRed;
                            parent.IsRed   = false;
                            r.IsRed        = true;
                            ReplaceChildOfNodeOrRoot(node3, parent, newChild);
                            if (parent == match)
                            {
                                parentOfMatch = newChild;
                            }
                            node3 = newChild;
                        }
                    }
                }
                int num = flag ? -1 : comparer.Compare(item, r.Item);
                if (num == 0)
                {
                    flag          = true;
                    match         = r;
                    parentOfMatch = parent;
                }
                node3  = parent;
                parent = r;
                if (num < 0)
                {
                    r = r.Left;
                }
                else
                {
                    r = r.Right;
                }
            }
            if (match != null)
            {
                ReplaceNode(match, parentOfMatch, parent, node3);
                count--;
            }
            if (this.Root != null)
            {
                this.Root.IsRed = false;
            }
            version++;
            return(flag);
        }
예제 #3
0
        /// <summary>
        /// Removes the member.
        /// </summary>
        /// <param name="item">The item.</param>
        /// <returns></returns>
        private bool RemoveMember(T item)
        {
            if (_root == null)
            {
                return(false);
            }

            ++Version;

            Node node1         = _root;
            Node node2         = null;
            Node node3         = null;
            Node match         = null;
            Node parentOfMatch = null;
            bool flag          = false;

            while (node1 != null)
            {
                if (Is2Node(node1))
                {
                    if (node2 == null)
                    {
                        node1.IsRed = true;
                    }
                    else
                    {
                        Node node4 = GetSibling(node1, node2);

                        if (node4.IsRed)
                        {
                            if (node2.Right == node4)
                            {
                                RotateLeft(node2);
                            }
                            else
                            {
                                RotateRight(node2);
                            }

                            node2.IsRed = true;
                            node4.IsRed = false;
                            ReplaceChildOfNodeOrRoot(node3, node2, node4);
                            node3 = node4;

                            if (node2 == match)
                            {
                                parentOfMatch = node4;
                            }

                            node4 = node2.Left == node1 ? node2.Right : node2.Left;
                        }

                        if (Is2Node(node4))
                        {
                            Merge2Nodes(node2, node1, node4);
                        }
                        else
                        {
                            TreeRotation treeRotation = RotationNeeded(node2, node1, node4);
                            Node         newChild     = null;

                            switch (treeRotation)
                            {
                            case TreeRotation.LeftRotation:
                                node4.Right.IsRed = false;
                                newChild          = RotateLeft(node2);
                                break;

                            case TreeRotation.RightRotation:
                                node4.Left.IsRed = false;
                                newChild         = RotateRight(node2);
                                break;

                            case TreeRotation.RightLeftRotation:
                                newChild = RotateRightLeft(node2);
                                break;

                            case TreeRotation.LeftRightRotation:
                                newChild = RotateLeftRight(node2);
                                break;
                            }

                            newChild.IsRed = node2.IsRed;
                            node2.IsRed    = false;
                            node1.IsRed    = true;
                            ReplaceChildOfNodeOrRoot(node3, node2, newChild);

                            if (node2 == match)
                            {
                                parentOfMatch = newChild;
                            }
                        }
                    }
                }

                var comparer = flag ? -1 : _comparer.Compare(item, node1.Item);

                if (comparer == 0)
                {
                    flag          = true;
                    match         = node1;
                    parentOfMatch = node2;
                }

                node3 = node2;
                node2 = node1;
                node1 = comparer >= 0 ? node1.Right : node1.Left;
            }

            if (match != null)
            {
                ReplaceNode(match, parentOfMatch, node2, node3);
                --Count;
            }

            if (_root != null)
            {
                _root.IsRed = false;
            }

            return(flag);
        }
예제 #4
0
        internal virtual bool DoRemove(T item)
        {
            if (_root == null)
            {
                return(false);
            }

            // Search for a node and then find its succesor.
            // Then copy the item from the succesor to the matching node and delete the successor.
            // If a node doesn't have a successor, we can replace it with its left child (if not empty.)
            // or delete the matching node.
            //
            // In top-down implementation, it is important to make sure the node to be deleted is not a 2-node.
            // Following code will make sure the node on the path is not a 2 Node.

            //
            // Even if we don't actually remove from the set, we may be altering its structure (by doing rotations
            // and such). so update version to disable any enumerators/subsets working on it.
            //
            _version++;

            Node current       = _root;
            Node parent        = null;
            Node grandParent   = null;
            Node match         = null;
            Node parentOfMatch = null;
            bool foundMatch    = false;

            while (current != null)
            {
                if (Is2Node(current))
                {     // fix up 2-Node
                    if (parent == null)
                    { // current is root. Mark it as red
                        current.IsRed = true;
                    }
                    else
                    {
                        Node sibling = GetSibling(current, parent);
                        if (sibling.IsRed)
                        {
                            // If parent is a 3-node, flip the orientation of the red link.
                            // We can acheive this by a single rotation
                            // This case is converted to one of other cased below.
                            Debug.Assert(!parent.IsRed, "parent must be a black node!");
                            if (parent.Right == sibling)
                            {
                                RotateLeft(parent);
                            }
                            else
                            {
                                RotateRight(parent);
                            }

                            parent.IsRed  = true;
                            sibling.IsRed = false;    // parent's color
                            // sibling becomes child of grandParent or root after rotation. Update link from grandParent or root
                            ReplaceChildOfNodeOrRoot(grandParent, parent, sibling);
                            // sibling will become grandParent of current node
                            grandParent = sibling;
                            if (parent == match)
                            {
                                parentOfMatch = sibling;
                            }

                            // update sibling, this is necessary for following processing
                            sibling = (parent.Left == current) ? parent.Right : parent.Left;
                        }
                        Debug.Assert(sibling != null || sibling.IsRed == false, "sibling must not be null and it must be black!");

                        if (Is2Node(sibling))
                        {
                            Merge2Nodes(parent, current, sibling);
                        }
                        else
                        {
                            // current is a 2-node and sibling is either a 3-node or a 4-node.
                            // We can change the color of current to red by some rotation.
                            TreeRotation rotation       = RotationNeeded(parent, current, sibling);
                            Node         newGrandParent = null;
                            switch (rotation)
                            {
                            case TreeRotation.RightRotation:
                                Debug.Assert(parent.Left == sibling, "sibling must be left child of parent!");
                                Debug.Assert(sibling.Left.IsRed, "Left child of sibling must be red!");
                                sibling.Left.IsRed = false;
                                newGrandParent     = RotateRight(parent);
                                break;

                            case TreeRotation.LeftRotation:
                                Debug.Assert(parent.Right == sibling, "sibling must be left child of parent!");
                                Debug.Assert(sibling.Right.IsRed, "Right child of sibling must be red!");
                                sibling.Right.IsRed = false;
                                newGrandParent      = RotateLeft(parent);
                                break;

                            case TreeRotation.RightLeftRotation:
                                Debug.Assert(parent.Right == sibling, "sibling must be left child of parent!");
                                Debug.Assert(sibling.Left.IsRed, "Left child of sibling must be red!");
                                newGrandParent = RotateRightLeft(parent);
                                break;

                            case TreeRotation.LeftRightRotation:
                                Debug.Assert(parent.Left == sibling, "sibling must be left child of parent!");
                                Debug.Assert(sibling.Right.IsRed, "Right child of sibling must be red!");
                                newGrandParent = RotateLeftRight(parent);
                                break;
                            }

                            newGrandParent.IsRed = parent.IsRed;
                            parent.IsRed         = false;
                            current.IsRed        = true;
                            ReplaceChildOfNodeOrRoot(grandParent, parent, newGrandParent);
                            if (parent == match)
                            {
                                parentOfMatch = newGrandParent;
                            }
                            grandParent = newGrandParent;
                        }
                    }
                }

                // we don't need to compare any more once we found the match
                int order = foundMatch ? -1 : _comparer.Compare(item, current.Item);
                if (order == 0)
                {
                    // save the matching node
                    foundMatch    = true;
                    match         = current;
                    parentOfMatch = parent;
                }

                grandParent = parent;
                parent      = current;

                if (order < 0)
                {
                    current = current.Left;
                }
                else
                {
                    current = current.Right;       // continue the search in  right sub tree after we find a match
                }
            }

            // move successor to the matching node position and replace links
            if (match != null)
            {
                ReplaceNode(match, parentOfMatch, parent, grandParent);
                --_count;
            }

            if (_root != null)
            {
                _root.IsRed = false;
            }

            return(foundMatch);
        }
예제 #5
0
    public bool Remove(Key key, Value value)
    {
        if (this.root == null)
        {
            return(false);
        }
        Node root          = this.root;
        Node parent        = null;
        Node node3         = null;
        Node match         = null;
        Node parentOfMatch = null;
        bool flag          = false;

        while (root != null)
        {
            if (Is2Node(root))
            {
                if (parent == null)
                {
                    root.IsRed = true;
                }
                else
                {
                    Node sibling = GetSibling(root, parent);
                    if (sibling.IsRed)
                    {
                        if (parent.Right == sibling)
                        {
                            RotateLeft(parent);
                        }
                        else
                        {
                            RotateRight(parent);
                        }
                        parent.IsRed  = true;
                        sibling.IsRed = false;
                        this.ReplaceChildOfNodeOrRoot(node3, parent, sibling);
                        node3 = sibling;
                        if (parent == match)
                        {
                            parentOfMatch = sibling;
                        }
                        sibling = (parent.Left == root) ? parent.Right : parent.Left;
                    }
                    if (Is2Node(sibling))
                    {
                        Merge2Nodes(parent, root, sibling);
                    }
                    else
                    {
                        TreeRotation rotation = RotationNeeded(parent, root, sibling);
                        Node         newChild = null;
                        switch (rotation)
                        {
                        case TreeRotation.LeftRotation:
                            sibling.Right.IsRed = false;
                            newChild            = RotateLeft(parent);
                            break;

                        case TreeRotation.RightRotation:
                            sibling.Left.IsRed = false;
                            newChild           = RotateRight(parent);
                            break;

                        case TreeRotation.RightLeftRotation:
                            newChild = RotateRightLeft(parent);
                            break;

                        case TreeRotation.LeftRightRotation:
                            newChild = RotateLeftRight(parent);
                            break;
                        }
                        newChild.IsRed = parent.IsRed;
                        parent.IsRed   = false;
                        root.IsRed     = true;
                        this.ReplaceChildOfNodeOrRoot(node3, parent, newChild);
                        if (parent == match)
                        {
                            parentOfMatch = newChild;
                        }
                        node3 = newChild;
                    }
                }
            }
            int num = flag ? -1 : this.comparer.Compare(key, root.Key);
            if (num == 0)
            {
                flag          = true;
                match         = root;
                parentOfMatch = parent;
            }
            node3  = parent;
            parent = root;
            if (num < 0)
            {
                root = root.Left;
            }
            else
            {
                root = root.Right;
            }
        }
        if (match != null)
        {
            if (match.Values.Remove(value))
            {
                this.count--;
            }
            if (match.Values.Count == 0)
            {
                this.ReplaceNode(match, parentOfMatch, parent, node3);
            }
        }
        if (this.root != null)
        {
            this.root.IsRed = false;
        }
        this.version++;
        return(flag);
    }
예제 #6
0
        public bool Remove(T item)
        {
            if (this.root == null)
            {
                return(false);
            }
            TreeSet <T> .Node node          = this.root;
            TreeSet <T> .Node node2         = null;
            TreeSet <T> .Node node3         = null;
            TreeSet <T> .Node node4         = null;
            TreeSet <T> .Node parentOfMatch = null;
            bool flag = false;

            while (node != null)
            {
                if (TreeSet <T> .Is2Node(node))
                {
                    if (node2 == null)
                    {
                        node.IsRed = true;
                    }
                    else
                    {
                        TreeSet <T> .Node node5 = TreeSet <T> .GetSibling(node, node2);

                        if (node5.IsRed)
                        {
                            if (node2.Right == node5)
                            {
                                TreeSet <T> .RotateLeft(node2);
                            }
                            else
                            {
                                TreeSet <T> .RotateRight(node2);
                            }
                            node2.IsRed = true;
                            node5.IsRed = false;
                            this.ReplaceChildOfNodeOrRoot(node3, node2, node5);
                            node3 = node5;
                            if (node2 == node4)
                            {
                                parentOfMatch = node5;
                            }
                            node5 = ((node2.Left == node) ? node2.Right : node2.Left);
                        }
                        if (TreeSet <T> .Is2Node(node5))
                        {
                            TreeSet <T> .Merge2Nodes(node2, node, node5);
                        }
                        else
                        {
                            TreeRotation treeRotation = TreeSet <T> .RotationNeeded(node2, node, node5);

                            TreeSet <T> .Node node6 = null;
                            switch (treeRotation)
                            {
                            case TreeRotation.LeftRotation:
                                node5.Right.IsRed = false;
                                node6             = TreeSet <T> .RotateLeft(node2);

                                break;

                            case TreeRotation.RightRotation:
                                node5.Left.IsRed = false;
                                node6            = TreeSet <T> .RotateRight(node2);

                                break;

                            case TreeRotation.RightLeftRotation:
                                node6 = TreeSet <T> .RotateRightLeft(node2);

                                break;

                            case TreeRotation.LeftRightRotation:
                                node6 = TreeSet <T> .RotateLeftRight(node2);

                                break;
                            }
                            node6.IsRed = node2.IsRed;
                            node2.IsRed = false;
                            node.IsRed  = true;
                            this.ReplaceChildOfNodeOrRoot(node3, node2, node6);
                            if (node2 == node4)
                            {
                                parentOfMatch = node6;
                            }
                        }
                    }
                }
                int num = flag ? -1 : this.comparer.Compare(item, node.Item);
                if (num == 0)
                {
                    flag          = true;
                    node4         = node;
                    parentOfMatch = node2;
                }
                node3 = node2;
                node2 = node;
                if (num < 0)
                {
                    node = node.Left;
                }
                else
                {
                    node = node.Right;
                }
            }
            if (node4 != null)
            {
                this.ReplaceNode(node4, parentOfMatch, node2, node3);
                this.count--;
            }
            if (this.root != null)
            {
                this.root.IsRed = false;
            }
            this.version++;
            return(flag);
        }