예제 #1
0
        public TKey GetMaxKey()
        {
            RedBlackNode <TKey, TValue> workNode = _treeBaseNode;

            if (workNode == null || workNode == SentinelNode)
            {
                throw (new RedBlackException(Properties.Resources.ExceptionTreeIsEmpty));
            }

            // traverse to the extreme right to find the largest key
            while (workNode.Right != SentinelNode)
            {
                workNode = workNode.Right;
            }

            _lastNodeFound = workNode;

            return(workNode.Key);
        }
예제 #2
0
        ///<summary>
        /// Balance Tree After Insert
        /// Additions to red-black trees usually destroy the red-black
        /// properties. Examine the tree and restore. Rotations are normally
        /// required to restore it
        ///</summary>
        private void BalanceTreeAfterInsert(RedBlackNode <TKey, TValue> insertedNode)
        {
            // x and y are used as variable names for brevity, in a more formal
            // implementation, you should probably change the names

            // maintain red-black tree properties after adding newNode
            while (insertedNode != _treeBaseNode && insertedNode.Parent.Color == RedBlackNodeType.Red)
            {
                // Parent node is .Colored red;
                RedBlackNode <TKey, TValue> workNode;
                if (insertedNode.Parent == insertedNode.Parent.Parent.Left) // determine traversal path
                {                                                           // is it on the Left or Right subtree?
                    workNode = insertedNode.Parent.Parent.Right;            // get uncle
                    if (workNode != null && workNode.Color == RedBlackNodeType.Red)
                    {                                                       // uncle is red; change x's Parent and uncle to black
                        insertedNode.Parent.Color = RedBlackNodeType.Black;
                        workNode.Color            = RedBlackNodeType.Black;
                        // grandparent must be red. Why? Every red node that is not
                        // a leaf has only black children
                        insertedNode.Parent.Parent.Color = RedBlackNodeType.Red;
                        insertedNode = insertedNode.Parent.Parent;      // continue loop with grandparent
                    }
                    else
                    {
                        // uncle is black; determine if newNode is greater than Parent
                        if (insertedNode == insertedNode.Parent.Right)
                        {       // yes, newNode is greater than Parent; rotate Left
                            // make newNode a Left child
                            insertedNode = insertedNode.Parent;
                            RotateLeft(insertedNode);
                        }
                        // no, newNode is less than Parent
                        insertedNode.Parent.Color        = RedBlackNodeType.Black; // make Parent black
                        insertedNode.Parent.Parent.Color = RedBlackNodeType.Red;   // make grandparent black
                        RotateRight(insertedNode.Parent.Parent);                   // rotate right
                    }
                }
                else
                {       // newNode's Parent is on the Right subtree
                    // this code is the same as above with "Left" and "Right" swapped
                    workNode = insertedNode.Parent.Parent.Left;
                    if (workNode != null && workNode.Color == RedBlackNodeType.Red)
                    {
                        insertedNode.Parent.Color        = RedBlackNodeType.Black;
                        workNode.Color                   = RedBlackNodeType.Black;
                        insertedNode.Parent.Parent.Color = RedBlackNodeType.Red;
                        insertedNode = insertedNode.Parent.Parent;
                    }
                    else
                    {
                        if (insertedNode == insertedNode.Parent.Left)
                        {
                            insertedNode = insertedNode.Parent;
                            RotateRight(insertedNode);
                        }
                        insertedNode.Parent.Color        = RedBlackNodeType.Black;
                        insertedNode.Parent.Parent.Color = RedBlackNodeType.Red;
                        RotateLeft(insertedNode.Parent.Parent);
                    }
                }
            }
            _treeBaseNode.Color = RedBlackNodeType.Black;               // rbTree should always be black
        }
예제 #3
0
 ///<summary>
 /// BalanceTreeAfterDelete
 /// Deletions from red-black trees may destroy the red-black
 /// properties. Examine the tree and restore. Rotations are normally
 /// required to restore it
 ///</summary>
 private void BalanceTreeAfterDelete(RedBlackNode <TKey, TValue> linkedNode)
 {
     // maintain Red-Black tree balance after deleting node
     while (linkedNode != _treeBaseNode && linkedNode.Color == RedBlackNodeType.Black)
     {
         RedBlackNode <TKey, TValue> workNode;
         // determine sub tree from parent
         if (linkedNode == linkedNode.Parent.Left)
         {
             // y is x's sibling
             workNode = linkedNode.Parent.Right;
             if (workNode.Color == RedBlackNodeType.Red)
             {
                 // x is black, y is red - make both black and rotate
                 linkedNode.Parent.Color = RedBlackNodeType.Red;
                 workNode.Color          = RedBlackNodeType.Black;
                 RotateLeft(linkedNode.Parent);
                 workNode = linkedNode.Parent.Right;
             }
             if (workNode.Left.Color == RedBlackNodeType.Black &&
                 workNode.Right.Color == RedBlackNodeType.Black)
             {
                 // children are both black
                 // change parent to red
                 workNode.Color = RedBlackNodeType.Red;
                 // move up the tree
                 linkedNode = linkedNode.Parent;
             }
             else
             {
                 if (workNode.Right.Color == RedBlackNodeType.Black)
                 {
                     workNode.Left.Color = RedBlackNodeType.Black;
                     workNode.Color      = RedBlackNodeType.Red;
                     RotateRight(workNode);
                     workNode = linkedNode.Parent.Right;
                 }
                 linkedNode.Parent.Color = RedBlackNodeType.Black;
                 workNode.Color          = linkedNode.Parent.Color;
                 workNode.Right.Color    = RedBlackNodeType.Black;
                 RotateLeft(linkedNode.Parent);
                 linkedNode = _treeBaseNode;
             }
         }
         else
         {       // right subtree - same as code above with right and left swapped
             workNode = linkedNode.Parent.Left;
             if (workNode.Color == RedBlackNodeType.Red)
             {
                 linkedNode.Parent.Color = RedBlackNodeType.Red;
                 workNode.Color          = RedBlackNodeType.Black;
                 RotateRight(linkedNode.Parent);
                 workNode = linkedNode.Parent.Left;
             }
             if (workNode.Right.Color == RedBlackNodeType.Black &&
                 workNode.Left.Color == RedBlackNodeType.Black)
             {
                 workNode.Color = RedBlackNodeType.Red;
                 linkedNode     = linkedNode.Parent;
             }
             else
             {
                 if (workNode.Left.Color == RedBlackNodeType.Black)
                 {
                     workNode.Right.Color = RedBlackNodeType.Black;
                     workNode.Color       = RedBlackNodeType.Red;
                     RotateLeft(workNode);
                     workNode = linkedNode.Parent.Left;
                 }
                 workNode.Color          = linkedNode.Parent.Color;
                 linkedNode.Parent.Color = RedBlackNodeType.Black;
                 workNode.Left.Color     = RedBlackNodeType.Black;
                 RotateRight(linkedNode.Parent);
                 linkedNode = _treeBaseNode;
             }
         }
     }
     linkedNode.Color = RedBlackNodeType.Black;
 }
예제 #4
0
        ///<summary>
        /// Delete
        /// Delete a node from the tree and restore red black properties
        ///</summary>
        private void Delete(RedBlackNode <TKey, TValue> deleteNode)
        {
            // A node to be deleted will be:
            //		1. a leaf with no children
            //		2. have one child
            //		3. have two children
            // If the deleted node is red, the red black properties still hold.
            // If the deleted node is black, the tree needs rebalancing

            // work node
            RedBlackNode <TKey, TValue> workNode;

            // find the replacement node (the successor to x) - the node one with
            // at *most* one child.
            if (deleteNode.Left == SentinelNode || deleteNode.Right == SentinelNode)
            {
                // node has sentinel as a child
                workNode = deleteNode;
            }
            else
            {
                // z has two children, find replacement node which will
                // be the leftmost node greater than z
                // traverse right subtree
                workNode = deleteNode.Right;
                // to find next node in sequence
                while (workNode.Left != SentinelNode)
                {
                    workNode = workNode.Left;
                }
            }

            // at this point, y contains the replacement node. it's content will be copied
            // to the valules in the node to be deleted

            // x (y's only child) is the node that will be linked to y's old parent.
            RedBlackNode <TKey, TValue> linkedNode = workNode.Left != SentinelNode
                                                 ? workNode.Left
                                                 : workNode.Right;

            // replace x's parent with y's parent and
            // link x to proper subtree in parent
            // this removes y from the chain
            linkedNode.Parent = workNode.Parent;
            if (workNode.Parent != null)
            {
                if (workNode == workNode.Parent.Left)
                {
                    workNode.Parent.Left = linkedNode;
                }
                else
                {
                    workNode.Parent.Right = linkedNode;
                }
            }
            else
            {
                // make x the root node
                _treeBaseNode = linkedNode;
            }

            // copy the values from y (the replacement node) to the node being deleted.
            // note: this effectively deletes the node.
            if (workNode != deleteNode)
            {
                deleteNode.Key  = workNode.Key;
                deleteNode.Data = workNode.Data;
            }

            if (workNode.Color == RedBlackNodeType.Black)
            {
                BalanceTreeAfterDelete(linkedNode);
            }

            _lastNodeFound = SentinelNode;

            Interlocked.Decrement(ref _count);
            InvokeOnRemove(new RedBlackEventArgs <TKey, TValue> {
                Item = deleteNode.Data, Key = deleteNode.Key
            });
        }
예제 #5
0
 ///<summary>
 /// Clear
 /// Empties or clears the tree
 ///</summary>
 public void Clear()
 {
     _treeBaseNode = SentinelNode;
     _count        = 0;
     InvokeOnClear(new EventArgs());
 }