Пример #1
0
        /// <summary>
        /// Transplants one subtree with another subtree.
        /// </summary>
        /// <param name="first"> First subtree.</param>
        /// <param name="second"> Second subtree.</param>
        private void Transplant(NodeRB <TKey, TValue> firstSubTree, NodeRB <TKey, TValue> secondSubTree)
        {
            //if first subtree has no parent then make the second subtree the root of the tree
            if (firstSubTree.Parent == nilNode)
            {
                this.root = secondSubTree;
            }

            //else if first subtree is a left child
            //then make second subtree the left child of first subtree's parent
            else if (firstSubTree == firstSubTree.Parent.Left)
            {
                firstSubTree.Parent.Left = secondSubTree;
            }

            //otherwise if first subtree is a right child
            //then make second subtree the right child of first subtree's parent
            else
            {
                firstSubTree.Parent.Right = secondSubTree;
            }

            //first subtree's parent becomes second subtree's parent
            secondSubTree.Parent = firstSubTree.Parent;
        }
Пример #2
0
        /// <summary>
        /// Gets the node with the passed key,if it exists.
        /// </summary>
        /// <param name="key"> Key. </param>
        /// <returns> Returns the node with the specified key,if it exist,and null;otherwise.</returns>
        private NodeRB <TKey, TValue> GetRBNode(TKey key)
        {
            //variable for storing CompareTo value
            int comparison;
            NodeRB <TKey, TValue> tempNode = this.root;

            while (tempNode != nilNode)
            {
                //comparing keys
                comparison = key.CompareTo(tempNode.Key);

                //if the key is greater go to the right
                if (comparison > 0)
                {
                    tempNode = tempNode.Right;
                }

                //else if key is less then go to the left
                else if (comparison < 0)
                {
                    tempNode = tempNode.Left;
                }

                //if key is equal to tempNode key then the node is found
                //return the found node
                else
                {
                    return(tempNode);
                }
            }

            //return null if the node with the given key is not found
            return(null);
        }
Пример #3
0
 /// <summary>
 /// Creates new instance of red-black tree node
 /// </summary>
 /// <param name="key"> Key of node.</param>
 /// <param name="value"> Value of node.</param>
 /// <param name="color"> Color of node.</param>
 /// <param name="parent"> Parent of node.</param>
 /// <param name="left"> Left child of node.</param>
 /// <param name="right"> Right child of node.</param>
 public NodeRB(TKey key, TValue value, NodeColor color = NodeColor.Black,
               NodeRB <TKey, TValue> parent            = null, NodeRB <TKey, TValue> left = null, NodeRB <TKey, TValue> right = null)
 {
     this.Key    = key;
     this.Value  = value;
     this.Color  = color;
     this.Left   = left;
     this.Right  = right;
     this.Parent = parent;
 }
Пример #4
0
        /// <summary>
        /// Gets the element containing minimum key in the given subtree.
        /// </summary>
        /// <param name="node"> Node.</param>
        /// <returns> Returns the element containing minimum key in the given subtree. </returns>
        private static NodeRB <TKey, TValue> MinimumKeyNode(NodeRB <TKey, TValue> node)
        {
            NodeRB <TKey, TValue> temp = node;

            //moving to the leftmost node in the given tree
            //because in binary search tree the minimal key is in the leftmost node
            while (temp.Left != nilNode)
            {
                temp = temp.Left;
            }

            return(temp);
        }
Пример #5
0
        /// <summary>
        /// Gets the collection of all elements in the dictionary.
        /// </summary>
        /// <returns> Returns the collection of all elements in the dictionary.</returns>
        private List <NodeRB <TKey, TValue> > GetAllElements()
        {
            List <NodeRB <TKey, TValue> > list = new List <NodeRB <TKey, TValue> >();
            NodeRB <TKey, TValue>         tempNode = this.root, predecessor;

            //doing inorder traversal using James Hiram Morris algorithm
            while (tempNode != nilNode)
            {
                //if the node's left child is nilNode
                //then add node to collection and move to the right
                if (tempNode.Left == nilNode)
                {
                    list.Add(tempNode);
                    tempNode = tempNode.Right;
                }

                //otherwise need to find the inorder predecessor of the tempNode
                else
                {
                    predecessor = tempNode.Left;
                    while (predecessor.Right != nilNode && predecessor.Right != nilNode)
                    {
                        predecessor = predecessor.Right;
                    }

                    //if inorder predecessor doesn't have right child then make tempNode its right child
                    if (predecessor.Right == nilNode)
                    {
                        predecessor.Right = tempNode;
                        tempNode          = tempNode.Left;
                    }

                    //if predecessor has right child than add it to the list
                    //and move to the right
                    else
                    {
                        predecessor.Right = nilNode;
                        list.Add(tempNode);
                        tempNode = tempNode.Right;
                    }
                }
            }

            //return the list containing dictionary elements.
            return(list);
        }
Пример #6
0
        /// <summary>
        /// Stores the value of the element with the given key in the value parameter
        /// if corresponding element exists in the dictionary.
        /// </summary>
        /// <param name="key"> Key.</param>
        /// <param name="value"> Value.</param>
        /// <returns> Returns false if the element with the given key exists in the dictionary and false;otherwise.</returns>
        public bool TryGetValue(TKey key, out TValue value)
        {
            NodeRB <TKey, TValue> node = this.GetRBNode(key);

            //if node is found then set the value and return true
            if (node != null)
            {
                value = node.Value;
                return(true);
            }

            //otherwise return false
            else
            {
                value = default(TValue);
                return(false);
            }
        }
Пример #7
0
        /// <summary>
        /// Rotates the tree  starting with the given subtree to the left.
        /// </summary>
        /// <param name="node"> Node.</param>
        private void LeftRotate(NodeRB <TKey, TValue> node)
        {
            //setting the Right child of node to temp
            NodeRB <TKey, TValue> temp = node.Right;

            //temp's left child becomes the right child of node
            node.Right = temp.Left;

            //if the right child of node has left child
            if (temp.Left != nilNode)
            {
                temp.Left.Parent = node;
            }

            temp.Parent = node.Parent;

            //if node doesn't have parent then right child of node becomes the root of tree
            if (node.Parent == nilNode)
            {
                this.root = temp;
            }

            //else if node is a left child then right child of node becomes the
            //left child of node's parent
            else if (node == node.Parent.Left)
            {
                node.Parent.Left = temp;
            }

            //otherwise becomes right child
            else
            {
                node.Parent.Right = temp;
            }

            //putting node on the left of temp
            temp.Left   = node;
            node.Parent = temp;
        }
Пример #8
0
        /// <summary>
        /// Gets or sets the value of the element with the given key.
        /// </summary>
        /// <param name="key"> Key.</param>
        /// <returns> Returns value.</returns>
        public TValue this[TKey key]
        {
            //gets the value with the specified key
            get
            {
                NodeRB <TKey, TValue> node = this.GetRBNode(key);

                //if element is found return the value

                if (node != null)
                {
                    return(node.Value);
                }

                //else throw exception
                else
                {
                    throw new KeyNotFoundException("Element with the given key doesn't exist in the dictioanry.");
                }
            }

            //sets the value
            set
            {
                NodeRB <TKey, TValue> node = this.GetRBNode(key);

                //if the element is found then set the value
                if (node != null)
                {
                    node.Value = value;
                }

                //else throw an exception
                else
                {
                    this.Insert(key, value);
                }
            }
        }
Пример #9
0
        /// <summary>
        /// Rotates the tree with the given subtree to the right
        /// </summary>
        /// <param name="node"></param>
        private void RightRotate(NodeRB <TKey, TValue> node)
        {
            //setting the left child of node to temp
            NodeRB <TKey, TValue> temp = node.Left;

            //temp's right child becomes the left child of node
            node.Left = temp.Right;

            //if the left child of node doesn't have right child
            if (temp.Right != nilNode)
            {
                temp.Right.Parent = node;
            }

            temp.Parent = node.Parent;

            //if node doesn't have parent then left child of node becomes the root of the tree
            if (node.Parent == nilNode)
            {
                this.root = temp;
            }

            //else if node is a right child
            else if (node == node.Parent.Right)
            {
                node.Parent.Right = temp;
            }

            //otherwis if node is a left child
            else
            {
                node.Parent.Left = temp;
            }

            //putting node on the right of its left child
            temp.Left   = node;
            node.Parent = temp;
        }
Пример #10
0
        /// <summary>
        /// Fixes the red-black tree after deletion of a node.
        /// </summary>
        /// <param name="node"> Node. </param>
        private void DeleteFixup(NodeRB <TKey, TValue> fixupNode)
        {
            NodeRB <TKey, TValue> temp;

            //iterating all over the tree to fix up
            while (fixupNode != this.root && fixupNode.Color == NodeColor.Black)
            {
                //if fixupNode is a left child
                if (fixupNode == fixupNode.Parent.Left)
                {
                    //save the sibling of fixupNode
                    temp = fixupNode.Parent.Right;

                    //if the color of fixupNode's sibling is red
                    if (temp.Color == NodeColor.Red)
                    {
                        //make the sibling's color black,parent's color - red
                        temp.Color             = NodeColor.Black;
                        fixupNode.Parent.Color = NodeColor.Red;

                        //rotate the subtree starting with the parent of fixupNode
                        this.LeftRotate(fixupNode.Parent);

                        //update the sibling
                        temp = fixupNode.Parent.Right;
                    }

                    if (temp == nilNode)
                    {
                        return;
                    }
                    //if (temp != nilNode)
                    //if both of temp's children are black

                    if (temp.Left.Color == NodeColor.Black && temp.Right.Color == NodeColor.Black)
                    {
                        temp.Color = NodeColor.Red;

                        //continue with the parent
                        fixupNode = fixupNode.Parent;
                    }

                    //if only the right child of temp is black
                    else
                    {
                        if (temp.Right.Color == NodeColor.Black)
                        {
                            //update colors
                            temp.Left.Color = NodeColor.Black;
                            temp.Color      = NodeColor.Red;

                            //rotate the subtree starting with temp
                            this.RightRotate(temp);

                            //update temp
                            temp = fixupNode.Parent.Right;
                        }


                        //otherwise
                        //update colors
                        temp.Color             = fixupNode.Parent.Color;
                        fixupNode.Parent.Color = temp.Right.Color = NodeColor.Black;

                        //rotate the subtree starting with the parent of fixupNode
                        this.LeftRotate(fixupNode.Parent);
                        //store root in temp
                        temp = this.root;
                    }
                }
                //otherwise if fixupNode is a right child
                //doing the same only exchanging right and left because here we have symmetry
                else
                {
                    temp = fixupNode.Parent.Left;
                    if (temp == nilNode)
                    {
                        return;
                    }
                    //if sibling of fixupNode is red
                    if (temp.Color == NodeColor.Red)
                    {
                        //update colors
                        temp.Color             = NodeColor.Black;
                        fixupNode.Parent.Color = NodeColor.Red;

                        //rotate to the right starting with the parent
                        this.RightRotate(fixupNode.Parent);

                        //update sibling
                        temp = fixupNode.Parent.Left;
                    }

                    //if the sibling's children are black
                    if (temp.Left.Color == NodeColor.Black && temp.Right.Color == NodeColor.Black)
                    {
                        temp.Color = NodeColor.Red;
                        fixupNode  = fixupNode.Parent;
                    }

                    //if only the left child of sibling is black
                    else
                    {
                        if (temp.Left.Color == NodeColor.Black)
                        {
                            //update colors
                            temp.Right.Color = NodeColor.Black;
                            temp.Color       = NodeColor.Red;

                            //rotate the subtree starting with the sibling
                            this.LeftRotate(temp);

                            //update sibling
                            temp = fixupNode.Parent.Left;
                        }

                        //setting colors
                        temp.Color             = fixupNode.Parent.Color;
                        fixupNode.Parent.Color = temp.Left.Color = NodeColor.Black;

                        //rotate the subtree starting with sibling
                        this.RightRotate(temp);

                        //update sibling
                        temp = this.root;
                    }
                }
                temp.Color = NodeColor.Black;
            }
        }
Пример #11
0
        /// <summary>
        /// Deletes the element with specified key from the dictionary if it exists there.
        /// </summary>
        /// <param name="key"> Key.</param>
        private bool Delete(TKey key)
        {
            NodeRB <TKey, TValue> node = this.GetRBNode(key);

            //if there is no element with the given key then return
            if (node == null)
            {
                return(false);
            }

            //if the node is found then delete

            NodeRB <TKey, TValue> temp = node, fixupNode;
            NodeColor             tempInitialColor = temp.Color;

            //if node doesn't have left child
            if (node.Left == nilNode)
            {
                //fixupNode becomes the same as the node's right child
                fixupNode = node.Right;

                //transplant node and node's right child
                this.Transplant(node, node.Right);
            }

            //else if node has left child but doesn't have right child
            else if (node.Right == nilNode)
            {
                //make fixupNode node's left child
                fixupNode = node.Left;

                //transplant node and node's left child
                this.Transplant(node, node.Left);
            }

            //otherwise if node  have 2 children
            else
            {
                //temp becomes the same as the leftmost node of node's righ subtree
                temp = MinimumKeyNode(node.Right);

                //update tempInitialColor
                tempInitialColor = temp.Color;

                //update fixupNode
                fixupNode = temp.Right;

                //if node is the right child of updated temp
                //make temp the parent of updated fixupNode
                if (temp.Parent == node)
                {
                    fixupNode.Parent = temp;
                }

                //otherwise
                else
                {
                    //transplant temp and the right child of temp
                    this.Transplant(temp, temp.Right);

                    //the right child of node becomes the right child of temp
                    temp.Right = node.Right;

                    //temp becomes the parent of temp right
                    temp.Right.Parent = temp;
                }

                //transplant node and temp subtrees
                this.Transplant(node, temp);

                //update corresponding properties of temp
                temp.Left        = node.Left;
                temp.Left.Parent = temp;
                temp.Color       = node.Color;
            }
            //if the initial color of temp is black then red-black tree needs to be fixed
            //the new tree must save the properties of red-black tree
            if (tempInitialColor == NodeColor.Black)
            {
                this.DeleteFixup(fixupNode);
            }

            //decrement Count property of dictionary because one item is removed
            --this.Count;
            return(true);
        }
Пример #12
0
        /// <summary>
        /// Fixes the Red-Black tree after insertion
        /// </summary>
        /// <param name="node"> Node. </param>
        private void InsertFixup(NodeRB <TKey, TValue> node)
        {
            NodeRB <TKey, TValue> temp;

            //starting Red-Black fixing process
            while (node != this.root && node.Parent.Color == NodeColor.Red)
            {
                //if node's parent is a left child
                if (node.Parent == node.Parent.Parent.Left)
                {
                    //temp becomes the uncle of node
                    temp = node.Parent.Parent.Right;

                    //if the color of node's uncle is red
                    if (temp.Color == NodeColor.Red)
                    {
                        //the color of node's parent and node's uncle becomes black
                        node.Parent.Color = temp.Color = NodeColor.Black;

                        //the color of node's grandparent becomes red
                        node.Parent.Parent.Color = NodeColor.Red;

                        //node becomes the grandparent of node
                        node = node.Parent.Parent;
                    }

                    //else if the color of node's uncle is not red and node is a right child
                    else
                    {
                        if (node == node.Parent.Right)
                        {
                            //node becomes its parent
                            node = node.Parent;

                            //left rotate starting with node
                            this.LeftRotate(node);
                        }

                        //otherwise node's parent color becomes black,grandparent's color becomes red
                        //and rotate to the right starting with node's grandparent
                        node.Parent.Color        = NodeColor.Black;
                        node.Parent.Parent.Color = NodeColor.Red;

                        this.RightRotate(node.Parent.Parent);
                    }
                }

                //otherwise if node's parent is a right child
                else
                {
                    //temp becomes the uncle of node
                    temp = node.Parent.Parent.Left;

                    //if the color of node's uncle is red
                    if (temp.Color == NodeColor.Red)
                    {
                        //the color of node's parent and uncle becomes black
                        node.Parent.Color = temp.Color = NodeColor.Black;

                        //the color of node's grandparent becomes red
                        node.Parent.Parent.Color = NodeColor.Red;

                        //node becomes the grandparent of node
                        node = node.Parent.Parent;
                    }

                    //else if the color of node's uncle is not red and node is a left child
                    else
                    {
                        if (node == node.Parent.Left)
                        {
                            //node becomes its parent
                            node = node.Parent;

                            //rotate the subtree starting with node to the right
                            this.RightRotate(node);
                        }

                        //otherwise
                        //the color of node's parent becomes black,the color of grandparent becomes red
                        node.Parent.Color        = NodeColor.Black;
                        node.Parent.Parent.Color = NodeColor.Red;

                        //rotate the subtree starting with node's grandparent to the left
                        this.LeftRotate(node.Parent.Parent);
                    }
                }
            }

            //set the color of the root as black
            //because the color of the root of Red-Black tree must be black.
            this.root.Color = NodeColor.Black;
        }
Пример #13
0
        /// <summary>
        /// Inserts new node to the tree with the given key and value,if there is no
        /// other element with that key
        /// </summary>
        /// <param name="key"> Key. </param>
        /// <param name="value"> Value. </param>
        private void Insert(TKey key, TValue value)
        {
            NodeRB <TKey, TValue> newNode = new NodeRB <TKey, TValue>(key, value, NodeColor.Red, null, nilNode, nilNode);
            NodeRB <TKey, TValue> temp = this.root, newNodeParent = nilNode;
            int comparison;

            //First of all we have to find the parent of newNode
            while (temp != nilNode)
            {
                //storing the parent
                //we need to do this because in the last iteration node will become nillNode
                newNodeParent = temp;

                comparison = key.CompareTo(temp.Key);

                //if the key is less than the key go to the left subtree
                if (comparison == -1)
                {
                    temp = temp.Left;
                }

                //else if the key is greater than the key go to the right subtree
                else if (comparison == 1)
                {
                    temp = temp.Right;
                }

                //otherwise if keys are equal
                //keys equality means that element with that key already exists in the dictionary
                //hence throw an exception
                else
                {
                    throw new Exception("Element with that key already exists in the dictionary");
                }
            }

            //set the parent of newNode
            newNode.Parent = newNodeParent;

            //if newNode doesn't have parents then it becomes the root of the tree
            if (newNode.Parent == nilNode)
            {
                this.root = newNode;
            }

            //else if the key is less then becomes the left child
            else if (newNode.Key.CompareTo(newNodeParent.Key) < 0)
            {
                newNode.Parent.Left = newNode;
            }

            //otherwise newNode becomes its parent right child
            else
            {
                newNode.Parent.Right = newNode;
            }

            newNode.Color = NodeColor.Red;

            //incrementing the Count property of dictionary because new item is added
            ++this.Count;

            //fix tree after insertion
            this.InsertFixup(newNode);
        }
Пример #14
0
 /// <summary>
 /// Creates new instance of dictionary.
 /// </summary>
 public DictionaryRB()
 {
     this.root  = nilNode;
     this.Count = 0;
 }
Пример #15
0
 /// <summary>
 /// Clears the dictionary.
 /// </summary>
 public void Clear()
 {
     this.root  = null;
     this.Count = 0;
 }