Пример #1
0
        ///<summary>
        /// GetMaxKey
        /// Returns the maximum key value
        ///</summary>
        public TKey GetMaxKey()
        {
            var work_node = _tree_base_node;

            if (work_node == null || work_node == RedBlackNode <TKey, TValue> .SentinelNode)
            {
                throw new RedBlackException(Properties.Resources.ExceptionTreeIsEmpty);
            }

            // traverse to the extreme right to find the largest key
            while (work_node.Right != RedBlackNode <TKey, TValue> .SentinelNode)
            {
                work_node = work_node.Right;
            }

            _last_node_found = work_node;

            return(work_node.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> inserted_node)
        {
            // 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 (inserted_node != _tree_base_node && inserted_node.Parent.Color == RedBlackNodeType.Red)
            {
                // Parent node is .Colored red;
                RedBlackNode <TKey, TValue> work_node;
                if (inserted_node.Parent == inserted_node.Parent.Parent.Left) // determine traversal path
                {                                                             // is it on the Left or Right subtree?
                    work_node = inserted_node.Parent.Parent.Right;            // get uncle
                    if (work_node != null && work_node.Color == RedBlackNodeType.Red)
                    {                                                         // uncle is red; change x's Parent and uncle to black
                        inserted_node.Parent.Color = RedBlackNodeType.Black;
                        work_node.Color            = RedBlackNodeType.Black;
                        // grandparent must be red. Why? Every red node that is not
                        // a leaf has only black children
                        inserted_node.Parent.Parent.Color = RedBlackNodeType.Red;
                        inserted_node = inserted_node.Parent.Parent;    // continue loop with grandparent
                    }
                    else
                    {
                        // uncle is black; determine if newNode is greater than Parent
                        if (inserted_node == inserted_node.Parent.Right)
                        {       // yes, newNode is greater than Parent; rotate Left
                            // make newNode a Left child
                            inserted_node = inserted_node.Parent;
                            RotateLeft(inserted_node);
                        }
                        // no, newNode is less than Parent
                        inserted_node.Parent.Color        = RedBlackNodeType.Black; // make Parent black
                        inserted_node.Parent.Parent.Color = RedBlackNodeType.Red;   // make grandparent black
                        RotateRight(inserted_node.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
                    work_node = inserted_node.Parent.Parent.Left;
                    if (work_node != null && work_node.Color == RedBlackNodeType.Red)
                    {
                        inserted_node.Parent.Color        = RedBlackNodeType.Black;
                        work_node.Color                   = RedBlackNodeType.Black;
                        inserted_node.Parent.Parent.Color = RedBlackNodeType.Red;
                        inserted_node = inserted_node.Parent.Parent;
                    }
                    else
                    {
                        if (inserted_node == inserted_node.Parent.Left)
                        {
                            inserted_node = inserted_node.Parent;
                            RotateRight(inserted_node);
                        }
                        inserted_node.Parent.Color        = RedBlackNodeType.Black;
                        inserted_node.Parent.Parent.Color = RedBlackNodeType.Red;
                        RotateLeft(inserted_node.Parent.Parent);
                    }
                }
            }
            _tree_base_node.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> linked_node)
 {
     // maintain Red-Black tree balance after deleting node
     while (linked_node != _tree_base_node && linked_node.Color == RedBlackNodeType.Black)
     {
         RedBlackNode <TKey, TValue> work_node;
         // determine sub tree from parent
         if (linked_node == linked_node.Parent.Left)
         {
             // y is x's sibling
             work_node = linked_node.Parent.Right;
             if (work_node.Color == RedBlackNodeType.Red)
             {
                 // x is black, y is red - make both black and rotate
                 linked_node.Parent.Color = RedBlackNodeType.Red;
                 work_node.Color          = RedBlackNodeType.Black;
                 RotateLeft(linked_node.Parent);
                 work_node = linked_node.Parent.Right;
             }
             if (work_node.Left.Color == RedBlackNodeType.Black &&
                 work_node.Right.Color == RedBlackNodeType.Black)
             {
                 // children are both black
                 // change parent to red
                 work_node.Color = RedBlackNodeType.Red;
                 // move up the tree
                 linked_node = linked_node.Parent;
             }
             else
             {
                 if (work_node.Right.Color == RedBlackNodeType.Black)
                 {
                     work_node.Left.Color = RedBlackNodeType.Black;
                     work_node.Color      = RedBlackNodeType.Red;
                     RotateRight(work_node);
                     work_node = linked_node.Parent.Right;
                 }
                 linked_node.Parent.Color = RedBlackNodeType.Black;
                 work_node.Color          = linked_node.Parent.Color;
                 work_node.Right.Color    = RedBlackNodeType.Black;
                 RotateLeft(linked_node.Parent);
                 linked_node = _tree_base_node;
             }
         }
         else
         {       // right subtree - same as code above with right and left swapped
             work_node = linked_node.Parent.Left;
             if (work_node.Color == RedBlackNodeType.Red)
             {
                 linked_node.Parent.Color = RedBlackNodeType.Red;
                 work_node.Color          = RedBlackNodeType.Black;
                 RotateRight(linked_node.Parent);
                 work_node = linked_node.Parent.Left;
             }
             if (work_node.Right.Color == RedBlackNodeType.Black &&
                 work_node.Left.Color == RedBlackNodeType.Black)
             {
                 work_node.Color = RedBlackNodeType.Red;
                 linked_node     = linked_node.Parent;
             }
             else
             {
                 if (work_node.Left.Color == RedBlackNodeType.Black)
                 {
                     work_node.Right.Color = RedBlackNodeType.Black;
                     work_node.Color       = RedBlackNodeType.Red;
                     RotateLeft(work_node);
                     work_node = linked_node.Parent.Left;
                 }
                 work_node.Color          = linked_node.Parent.Color;
                 linked_node.Parent.Color = RedBlackNodeType.Black;
                 work_node.Left.Color     = RedBlackNodeType.Black;
                 RotateRight(linked_node.Parent);
                 linked_node = _tree_base_node;
             }
         }
     }
     linked_node.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> delete_node)
        {
            // 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> work_node;

            // find the replacement node (the successor to x) - the node one with
            // at *most* one child.
            if (delete_node.Left == RedBlackNode <TKey, TValue> .SentinelNode ||
                delete_node.Right == RedBlackNode <TKey, TValue> .SentinelNode)
            {
                // node has sentinel as a child
                work_node = delete_node;
            }
            else
            {
                // z has two children, find replacement node which will
                // be the leftmost node greater than z
                // traverse right subtree
                work_node = delete_node.Right;
                // to find next node in sequence
                while (work_node.Left != RedBlackNode <TKey, TValue> .SentinelNode)
                {
                    work_node = work_node.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.
            var linked_node = work_node.Left != RedBlackNode <TKey, TValue> .SentinelNode
                                                 ? work_node.Left
                                                 : work_node.Right;

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

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

            if (work_node.Color == RedBlackNodeType.Black)
            {
                BalanceTreeAfterDelete(linked_node);
            }

            _last_node_found = RedBlackNode <TKey, TValue> .SentinelNode;

            Interlocked.Decrement(ref _count);
            InvokeOnRemove(new RedBlackEventArgs <TKey, TValue> {
                Item = delete_node.Data, Key = delete_node.Key
            });
        }
Пример #5
0
 ///<summary>
 /// Clear
 /// Empties or clears the tree
 ///</summary>
 public void Clear()
 {
     _tree_base_node = RedBlackNode <TKey, TValue> .SentinelNode;
     _count          = 0;
     InvokeOnClear(new EventArgs());
 }