示例#1
0
        /// <summary>Adds a node to the tree.</summary>
        /// <param name="data">Data to be contained at the new node location.</param>
        /// <param name="key">Key used for comparison and lookup.</param>
        /// <exception cref="ArgumentNullException">Thrown if data is null.</exception>
        /// <exception cref="ArgumentException">Thrown if data already exists in the tree.</exception>
        /// <exception cref="ArgumentException">Thrown if key is not of type IComparable.</exception>
        public override void Add(TKey key, TValue data)
        {
            if (key == null)
            {
                throw new ArgumentNullException("key");
            }

            Node <TKey, TValue> parent = null;

            RedBlackNode <TKey, TValue> .Add(ref Root, ref parent, key, data);

            Count++;

            // Do a Debug Sanity Check on the Tree
            if (Root != null)
            {
                Root.Check();
            }
        }
示例#2
0
        /// <summary>Adds the given key and value to the tree at the current node.</summary>
        /// <param name="root">Node to add key/value pair to.</param>
        /// <param name="parent">Parent node of root.</param>
        /// <param name="key">Key used to index the value.</param>
        /// <param name="value">Value to add to the node</param>
        public static void Add(ref Node <TKey, TValue> root, ref Node <TKey, TValue> parent, TKey key, TValue value)
        {
            // See if the tree is empty
            if (root == null)
            {
                // Insert new node here. If parent is null this is the first node so it should be black -
                // otherwise make it red.
                root = new RedBlackNode <TKey, TValue>(key, value)
                {
                    Color = (parent == null) ? NodeColor.Black : NodeColor.Red
                };
                return;
            }

            // Compare items and determine which direction to search
            // Make sure that nResult is between -1 and 1
            int  nResult = key.CompareTo(root.Key);
            uint dir     = (nResult < 0) ? LEFT : RIGHT;

            if (nResult == 0)
            {
                throw new ArgumentException("Attempting to add duplicate item to the tree.  The items has a value of " + key.ToString(), "data");
            }
            else
            {
                // Insert into "dir" subtree
                RedBlackNode <TKey, TValue> rbRoot = (RedBlackNode <TKey, TValue>)root;
                Add(ref rbRoot.Nodes[dir], ref root, key, value);

                // Check for red-property violation with child
                rbRoot = (RedBlackNode <TKey, TValue>)root;
                RedBlackNode <TKey, TValue> rbChild = (RedBlackNode <TKey, TValue>)root[dir];
                if ((rbRoot.Color == NodeColor.Red) && (rbChild.Color == NodeColor.Red))
                {
                    FixRedViolation(ref parent, ref root, dir);
                }
            }
        }
示例#3
0
        /// <summary>Removes the node containing this data from the tree.</summary>
        /// <param name="key">Value to remove from the tree.</param>
        /// <exception cref="ArgumentNullException">Thrown if data is null.</exception>
        /// <exception cref="ArgumentException">Thrown if key is not of type IComparable.</exception>
        /// <remarks>If data does not exist in the tree, then the tree remains unchanged.  No exception is thrown.</remarks>
        public override bool Remove(TKey key)
        {
            if (key == null)
            {
                throw new ArgumentNullException("key");
            }

            bool blackDecrease = false;
            bool bFound        = false;

            if (RedBlackNode <TKey, TValue> .Remove(ref Root, key, ref blackDecrease, Node <TKey, TValue> .CompType.EQ_CMP) != null)
            {
                Count--;
                bFound = true;
            }

            // Do a Debug Sanity Check on the Tree
            if (Root != null)
            {
                Root.Check();
            }

            return(bFound);
        }
示例#4
0
        private static bool FixBlackViolation(ref Node <TKey, TValue> root, uint dir)
        {
            bool propagated = false;   // Initialize the return value

            // "dir" is the direction that just became deficient, the other
            // direction is the side that wasnt deleted from.
            uint otherDir = Opposite(dir);

            // Get the deficient subtree (if its exists) and its sibling
            RedBlackNode <TKey, TValue> child   = (RedBlackNode <TKey, TValue>)root[dir];
            RedBlackNode <TKey, TValue> sibling = (RedBlackNode <TKey, TValue>)root[otherDir];

            if (GetColor(child) == NodeColor.Red)
            {
                // Increase the black height of this entire subtree by
                // simply making the child black. In theory - this routine
                // will never be called if the child is red.
                child.Color = NodeColor.Black;
            }
            else if (GetColor(sibling) == NodeColor.Black)
            {
                // Need to know if the parent is red or not. If it is, then
                // any rotated result needs to have a red-root (and root will
                // need to change to black), otherwise any rotated result will
                // have a black root.
                bool blackParent = (GetColor(root) == NodeColor.Black);
                if (!blackParent)
                {
                    ((RedBlackNode <TKey, TValue>)root).Color = NodeColor.Black;
                }

                // Now look at the color of the sibling's children
                if (GetColor(sibling[dir]) == NodeColor.Red)
                {
                    // Need to change the color of this subtree if the parent is black
                    if (blackParent)
                    {
                        ((RedBlackNode <TKey, TValue>)sibling[dir]).Color = NodeColor.Black;
                    }

                    // Now rotate twice to make this subtree the new root
                    RotateTwice(ref root, dir);
                }
                else if (GetColor(sibling[otherDir]) == NodeColor.Red)
                {
                    // Need to change the color of this subtree
                    ((RedBlackNode <TKey, TValue>)sibling[otherDir]).Color = NodeColor.Black;

                    // If the root is red then exchange its color with the sibling
                    if (!blackParent)
                    {
                        sibling.Color = NodeColor.Red;
                    }

                    // Now rotate once to make the sibling the new root
                    RotateOnce(ref root, dir);
                }
                else
                {
                    // Make the sibling red
                    sibling.Color = NodeColor.Red;

                    // If the root was black we have fixed the black-property
                    // violation at this level by shortening the black height of
                    // the "dir" subtree, hence the problem has been propagated
                    // up to the next higher level.
                    propagated = blackParent;
                }
            }
            else
            {
                // First, perform a single rotation and flip the color of the
                // sibling and its "dir" subtree.
                sibling.Color = NodeColor.Black;
                ((RedBlackNode <TKey, TValue>)sibling[dir]).Color = NodeColor.Red;
                RotateOnce(ref root, dir);

                // Now check for a red-property violation with the sibling's
                // subtree (which after the rotation, is now in a different
                // position). Note that the sibling's former subtree is the
                // "nephew" or "niece" of the child.
                RedBlackNode <TKey, TValue> rbRoot   = (RedBlackNode <TKey, TValue>)root;
                RedBlackNode <TKey, TValue> tempNode = (RedBlackNode <TKey, TValue>)root[dir];
                Node <TKey, TValue>         niece    = root[dir][otherDir];

                if ((GetColor(niece[dir]) == NodeColor.Red) &&
                    (GetColor(niece[otherDir]) == NodeColor.Red))
                {
                    // change the color of the niece
                    ((RedBlackNode <TKey, TValue>)niece).Color = NodeColor.Black;

                    // No child, need an additional rotation
                    // (this time a double)
                    if (child == null)
                    {
                        RotateTwice(ref rbRoot.Nodes[dir], dir);
                    }
                }
                else if (GetColor(niece[dir]) == NodeColor.Red)
                {
                    FixRedViolation(ref rbRoot.Nodes[dir], ref tempNode.Nodes[otherDir], dir);
                }
                else if (GetColor(niece[otherDir]) == NodeColor.Red)
                {
                    FixRedViolation(ref rbRoot.Nodes[dir], ref tempNode.Nodes[otherDir], otherDir);
                }
            }

            return(propagated);
        }