コード例 #1
0
ファイル: RedBlackTree.cs プロジェクト: asm2025/essentialMix
        public override bool IsBalanced()
        {
            if (Root == null || Root.IsLeaf)
            {
                return(true);
            }

            // using levelOrder traversal
            // Root-Left-Right (Queue)
            Queue <RedBlackNode <T> > queue = new Queue <RedBlackNode <T> >(GetCapacityForQueueing(this));

            // Start at the root
            queue.Enqueue(Root);

            while (queue.Count > 0)
            {
                RedBlackNode <T> current = queue.Dequeue();

                // Queue the next nodes
                if (current.Left != null)
                {
                    if (!IsBalancedLocal(current.Left, current))
                    {
                        return(false);
                    }
                    queue.Enqueue(current.Left);
                }

                if (current.Right != null)
                {
                    if (!IsBalancedLocal(current.Right, current))
                    {
                        return(false);
                    }
                    queue.Enqueue(current.Right);
                }
            }
            return(true);
コード例 #2
0
ファイル: RedBlackTree.cs プロジェクト: asm2025/essentialMix
        /// <summary>
        /// Validates the node and its children.
        /// </summary>
        /// <param name="node"></param>
        /// <returns></returns>
        public override bool Validate(RedBlackNode <T> node)
        {
            if (node == null)
            {
                return(true);
            }

            T    previous = default(T);
            bool isValid = true, started = false;

            Iterate(node, e =>
            {
                if (!started)
                {
                    started  = true;
                    previous = e.Value;
                    return(true);
                }

                isValid = Comparer.IsLessThan(previous, e.Value);
                return(isValid);
            });
            return(isValid);
        }
コード例 #3
0
ファイル: RedBlackTree.cs プロジェクト: asm2025/essentialMix
        public override bool Remove(T value)
        {
            if (Root == null)
            {
                return(false);
            }

            /*
             * Search for a node and then find its successor then copy the item from the successor
             * 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.
             */
            RedBlackNode <T> current       = Root,
                             parent        = null,
                             grandParent   = null,
                             match         = null,
                             parentOfMatch = null;
            bool foundMatch = false;

            while (current != null)
            {
                if (Is2Node(current))
                {
                    if (parent == null)
                    {
                        current.Color = true;
                    }
                    else
                    {
                        RedBlackNode <T> sibling = GetSibling(current, parent);

                        if (sibling.Color)
                        {
                            /*
                             * If parent is a 3-node, flip the orientation of the red link.
                             * We can achieve this by a single rotation. This case is converted
                             * to one of other cased below.
                             */
                            Debug.Assert(!parent.Color, "parent must be a black node!");

                            if (ReferenceEquals(parent.Right, sibling))
                            {
                                RotateLeft(parent);
                            }
                            else
                            {
                                RotateRight(parent);
                            }

                            parent.Color  = true;
                            sibling.Color = false;
                            // 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 (ReferenceEquals(parent, match))
                            {
                                parentOfMatch = sibling;
                            }
                            // update sibling, this is necessary for following processing
                            sibling = (ReferenceEquals(parent.Left, current)
                                                                                ? parent.Right
                                                                                : parent.Left) ?? throw new Exception("Sibling must not be null!");
                        }

                        Debug.Assert(!sibling.Color, "Sibling 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.
                             */
                            RedBlackNode <T> newGrandParent;
                            Debug.Assert(IsRed(sibling.Left) || IsRed(sibling.Right), "sibling must have at least one red child");

                            if (IsRed(sibling.Left))
                            {
                                if (ReferenceEquals(parent.Left, current))
                                {
                                    // R L case
                                    Debug.Assert(parent.Right == sibling, "sibling must be left child of parent!");
                                    Debug.Assert(sibling.Left.Color, "Left child of sibling must be red!");
                                    newGrandParent = RotateRightLeft(parent);
                                }
                                else
                                {
                                    // R case
                                    Debug.Assert(parent.Left == sibling, "sibling must be left child of parent!");
                                    Debug.Assert(sibling.Left.Color, "Left child of sibling must be red!");
                                    sibling.Left.Color = false;
                                    newGrandParent     = RotateRight(parent);
                                }
                            }
                            else
                            {
                                if (ReferenceEquals(parent.Left, current))
                                {
                                    // L case
                                    Debug.Assert(parent.Right == sibling, "sibling must be left child of parent!");
                                    Debug.Assert(sibling.Right.Color, "Right child of sibling must be red!");
                                    sibling.Right.Color = false;
                                    newGrandParent      = RotateLeft(parent);
                                }
                                else
                                {
                                    // L R case
                                    Debug.Assert(parent.Left == sibling, "sibling must be left child of parent!");
                                    Debug.Assert(sibling.Right.Color, "Right child of sibling must be red!");
                                    newGrandParent = RotateLeftRight(parent);
                                }
                            }

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

                // we don't need to compare any more once we found the match
                int order = foundMatch
                                                                ? -1
                                                                : Comparer.Compare(value, current.Value);

                if (order == 0)
                {
                    // save the matching node
                    foundMatch    = true;
                    match         = current;
                    parentOfMatch = parent;
                }

                grandParent = parent;
                parent      = current;
                // continue the search in right sub-tree after we find a match
                current = order < 0
                                                        ? current.Left
                                                        : current.Right;
            }

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

            if (Root != null)
            {
                Root.Color = false;
            }
            return(true);
        }
コード例 #4
0
ファイル: RedBlackTree.cs プロジェクト: asm2025/essentialMix
        /// <inheritdoc />
        public override void Add(T value)
        {
            if (Root == null)
            {
                Root       = MakeNode(value);
                Root.Color = false;
                Count++;
                _version++;
                return;
            }

            RedBlackNode <T> current          = Root,
                             parent           = null,
                             grandParent      = null,
                             greatGrandParent = null;
            int order = 0;

            /*
             * If we can guarantee the node we found is not a 4-node, it would be easy to do insertion.
             * We split 4-nodes along the search path.
             */
            // find a parent
            while (current != null)
            {
                order = Comparer.Compare(value, current.Value);

                // duplicate values means nodes will never be balanced!
                if (order == 0)
                {
                    // We could have changed root node to red during the search process. Root needs to be set to black.
                    Root.Color = false;
                    throw new DuplicateKeyException();
                }

                // split a 4-node into two 2-nodes
                if (Is4Node(current))
                {
                    Split4Node(current);
                    // We could have introduced two consecutive red nodes after split. Fix that by rotation.
                    if (IsRed(parent) && grandParent != null)
                    {
                        Balance(current, ref parent, grandParent, greatGrandParent);
                    }
                }

                greatGrandParent = grandParent;
                grandParent      = parent;
                parent           = current;
                current          = order < 0
                                                        ? current.Left
                                                        : current.Right;
            }

            Debug.Assert(parent != null, "No parent node found for the new node.");

            RedBlackNode <T> node = MakeNode(value);

            if (order < 0)
            {
                parent !.Left = node;
            }
            else
            {
                parent !.Right = node;
            }

            // the new node will be red, so we will need to adjust the colors if parent node is also red
            if (parent.Color && grandParent != null)
            {
                Balance(node, ref parent, grandParent, greatGrandParent);
            }
            // Root node is always black
            Root.Color = false;
            Count++;
            _version++;
        }