예제 #1
0
 /// <summary>
 /// Used by AddTree before reinsertion of the node
 /// </summary>
 internal virtual void ClearRelations()
 {
     mColor  = RBTreeColor.Black;
     mLeft   = null;
     mRight  = null;
     mParent = null;
 }
예제 #2
0
        ///<summary>
        ///Return a pointer to the largest key smaller than x
        ///
        protected RBTreeNodeBase <T, P> Predecessor(RBTreeNodeBase <T, P> x)
        {
            RBTreeNodeBase <T, P> y;

            if (x.mLeft != null)
            {
                // If left is not NULL then go left one and
                // then keep going right until we find a node with
                // no right pointer.
                for (y = x.mLeft; y.mRight != null; y = y.mRight)
                {
                    ;
                }
            }
            else
            {
                // Go up the tree until we get to a node that is on the
                // right of its parent (or the root) and then return the
                // parent.
                y = x.mParent;
                while (y != null && x == y.mLeft)
                {
                    x = y;
                    y = y.mParent;
                }
            }
            return(y);
        }
예제 #3
0
 ///<summary>
 ///Tree constructor
 ///</summary>
 public RBTreeBase(bool unique)
 {
     mRoot     = null;
     mComparer = Comparer <T> .Default;
     mCount    = 0;
     mUnique   = unique;
 }
예제 #4
0
 ///<summary>
 ///Tree constructor with comparer
 ///</summary>
 public RBTreeBase(IComparer <T> aComparer, bool unique)
 {
     mRoot     = null;
     mComparer = aComparer;
     mCount    = 0;
     mUnique   = unique;
 }
예제 #5
0
        /// <summary>
        /// This method was added by Dmitriano. Re-adds root element to the three
        /// after Comparer has been changed.
        /// </summary>
        /// <param name="node"></param>
        void AddTree(RBTreeNodeBase <T, P> node)
        {
            if (node != null)
            {
                AddTree(node.Left);

                RBTreeNodeBase <T, P> right = node.Right;

                //reuse this node to avoid superfluous dynamic memory allocation
                node.ClearRelations();

                RBTreeNodeBase <T, P> result;
                bool insert = true;
                result = Traverse(ref insert, node.Key, node);

                Debug.Assert(result == node);

                if (!insert)
                {
                    throw new System.InvalidOperationException("A node alredy exists in the destination tree.");
                }

                mCount++;

                AddTree(right);
            }
        }
예제 #6
0
        ///<summary>
        ///Copy from other node
        ///</summary>
        internal virtual void CopyFrom(RBTreeNodeBase <T, P> z)
        {
            if (z.mLeft != null)
            {
                z.mLeft.mParent = this;
            }
            this.mLeft = z.mLeft;

            if (z.mRight != null)
            {
                z.mRight.mParent = this;
            }
            this.mRight = z.mRight;

            //2) replace z with this in the parent node
            if (z.mParent != null)
            {
                if (z.mParent.mLeft == z)
                {
                    z.mParent.SetLeft(this);
                }
                else
                {
                    z.mParent.SetRight(this);
                }
            }

            this.mColor = z.mColor;
            this.SetParent(z.mParent);
        }
예제 #7
0
 ///<summary>
 ///Set parent node
 ///</summary>
 internal override void SetParent(RBTreeNodeBase <T, RBOrderedNodeParam> value)
 {
     mParent = value;
     if (mParent != null)
     {
         mParent.OnUpdateCount();
     }
 }
예제 #8
0
        public int IndexOfKey(T key)
        {
            RBTreeNodeBase <T, RBOrderedNodeParam> node = Find(key);

            if (node == null)
            {
                return(-1);
            }

            return(GetOrder(node as RBOrderedTreeNode <T>));
        }
예제 #9
0
        ///<summary>
        /// Rotate our tree Right
        ///
        ///             X                                         Y
        ///           /   \                                     /   \
        ///          A     Y     <---rb_right_rotate(Y)        X     C
        ///              /   \                               /   \
        ///             B     C                             A     B
        ///
        /// N.B. This does not change the ordering.
        ///
        /// We assume that neither X or Y is NULL
        ///<summary>
        protected void RightRotate(RBTreeNodeBase <T, P> y)
        {
            RBTreeNodeBase <T, P> x;

            // set X
            x = y.mLeft;

            // Turn X's right subtree into Y's left subtree (move B)
            y.mLeft = x.mRight;

            // If B is not null, set it's parent to be Y
            if (x.mRight != null)
            {
                x.mRight.mParent = y;
            }

            // Set X's parent to be what Y's parent was
            x.mParent = y.mParent;

            // if Y was the root
            if (y.mParent == null)
            {
                mRoot = x;
            }
            else
            {
                // Set Y's parent's left or right pointer to be X
                if (y == y.mParent.mLeft)
                {
                    y.mParent.mLeft = x;
                }
                else
                {
                    y.mParent.mRight = x;
                }
            }

            // Put Y on X's right
            x.mRight = y;

            // Set Y's parent to be X
            y.mParent = x;

            y.OnUpdateCount();
        }
예제 #10
0
        ///<summary>
        /// Rotate our tree Left
        ///
        ///             X        rb_left_rotate(X)--->            Y
        ///           /   \                                     /   \
        ///          A     Y                                   X     C
        ///              /   \                               /   \
        ///             B     C                             A     B
        ///
        /// N.B. This does not change the ordering.
        ///
        /// We assume that neither X or Y is NULL
        ///<summary>
        protected void LeftRotate(RBTreeNodeBase <T, P> x)
        {
            RBTreeNodeBase <T, P> y;

            // set Y
            y = x.mRight;

            // Turn Y's left subtree into X's right subtree (move B)
            x.mRight = y.mLeft;

            // If B is not null, set it's parent to be X
            if (y.mLeft != null)
            {
                y.mLeft.mParent = x;
            }

            // Set Y's parent to be what X's parent was
            y.mParent = x.mParent;

            // if X was the root
            if (x.mParent == null)
            {
                mRoot = y;
            }
            else
            {
                // Set X's parent's left or right pointer to be Y
                if (x == x.mParent.mLeft)
                {
                    x.mParent.mLeft = y;
                }
                else
                {
                    x.mParent.mRight = y;
                }
            }

            // Put X on Y's left
            y.mLeft = x;

            // Set X's parent to be Y
            x.mParent = y;

            x.OnUpdateCount();
        }
예제 #11
0
        /// <summary>
        /// This method was added by Dmitriano. Re-adds removed node
        /// with cleared relations to the tree.
        /// </summary>
        /// <param name="node">A tree node previously deleted by Remove.</param>
        public void Add(ITreeNode <T> node)
        {
            RBTreeNodeBase <T, P> t_node = node as RBTreeNodeBase <T, P>;

            t_node.CheckRelationsCleared();

            bool insert = true;
            RBTreeNodeBase <T, P> key = Traverse(ref insert, t_node.Key, t_node);

            Debug.Assert(key == node);

            if (!insert)
            {
                throw new InvalidOperationException("Node already exists.");
            }

            mCount++;
        }
예제 #12
0
        ///<summary>
        ///Get order index of item
        ///This operation is O(logN) operation
        ///</summary>
        public int GetOrder(RBOrderedTreeNode <T> aItem)
        {
            RBTreeNodeBase <T, RBOrderedNodeParam> node = aItem;
            int idx = node.mParam.mRank;

            while (true)
            {
                if (node.mParent == null)
                {
                    break;
                }

                if (node.mParent.mRight == node)
                {
                    idx += node.mParent.mParam.mRank;
                }
                node = node.mParent;
            }
            return(idx - 1);
        }
예제 #13
0
        ///<summary>
        ///Get item by order index
        ///This operation is O(logN) operation
        ///</summary>
        public RBOrderedTreeNode <T> GetByOrder(int idx)
        {
            int m = idx + 1;
            RBTreeNodeBase <T, RBOrderedNodeParam> node = mRoot;

            while (node != null && m > 0)
            {
                if (m < node.mParam.mRank)
                {
                    node = node.mLeft;
                }
                else if (m > node.mParam.mRank)
                {
                    m    = m - node.mParam.mRank;
                    node = node.mRight;
                }
                else if (m == node.mParam.mRank)
                {
                    return(node as RBOrderedTreeNode <T>);
                }
            }
            return(null);
        }
예제 #14
0
 ///<summary>
 ///Set right node
 ///</summary>
 internal override void SetRight(RBTreeNodeBase <T, RBOrderedNodeParam> value)
 {
     mRight = value;
     OnUpdateCount();
 }
예제 #15
0
        ///<summary>
        ///Go trough tree and find the node by the key.
        ///Might add new node if node doesn't exist.
        ///node_to_reuse parameter added by Dmitriano to avoid superfluous dynamic memory allocation
        ///if node_to_reuse is not null aKey should be equal to node_to_reuse.Key
        ///</summary>
        internal RBTreeNodeBase <T, P> Traverse(ref bool aInsert, T aKey, RBTreeNodeBase <T, P> node_to_reuse = null)
        {
            RBTreeNodeBase <T, P> x, y, z;
            int cmp;

            //walk down the tree
            y = null;
            x = mRoot;
            while (x != null)
            {
                y   = x;
                cmp = mComparer.Compare(aKey, x.mKey);

                if (!mUnique && cmp == 0 && aInsert == true)
                {
                    cmp = 1;
                }

                if (cmp < 0)
                {
                    x = x.mLeft;
                }
                else if (cmp > 0)
                {
                    x = x.mRight;
                }
                else
                {
                    aInsert = false;
                    return(x);
                }
            }

            //x is null. return null if node must not be inserted
            if (!aInsert)
            {
                return(null);
            }

            if (node_to_reuse != null) //this condition was changed by Dmitriano
            {
                z = node_to_reuse;     //ignore aKey parameter here
            }
            else
            {
                z      = NewNode();
                z.mKey = aKey;
            }

            //x is null and insert operation is requested
            //create new node
            z.mParent = y;
            if (y == null)
            {
                mRoot = z;
            }
            else
            {
                cmp = mComparer.Compare(z.mKey, y.mKey);
                if (cmp == 0)
                {
                    cmp = 1;
                }
                if (cmp < 0)
                {
                    y.SetLeft(z);
                }
                else
                {
                    y.SetRight(z);
                }
            }
            z.mColor = RBTreeColor.Red;

            Balance(z);
            mRoot.mColor = RBTreeColor.Black;
            return(z);
        }
예제 #16
0
        ///<summary>
        ///Balance tree past inserting
        ///</summary>
        protected void Balance(RBTreeNodeBase <T, P> z)
        {
            RBTreeNodeBase <T, P> x, y;

            //Having added a red node, we must now walk back up the tree balancing
            //it, by a series of rotations and changing of colours
            x = z;

            //While we are not at the top and our parent node is red
            //N.B. Since the root node is garanteed black, then we
            //are also going to stop if we are the child of the root
            while (x != mRoot && (x.mParent.mColor == RBTreeColor.Red))
            {
                //if our parent is on the left side of our grandparent
                if (x.mParent == x.mParent.mParent.mLeft)
                {
                    //get the right side of our grandparent (uncle?)
                    y = x.mParent.mParent.mRight;
                    if (y != null && y.mColor == RBTreeColor.Red)
                    {
                        //make our parent black
                        x.mParent.mColor = RBTreeColor.Black;
                        //make our uncle black
                        y.mColor = RBTreeColor.Black;
                        //make our grandparent red
                        x.mParent.mParent.mColor = RBTreeColor.Red;
                        //now consider our grandparent
                        x = x.mParent.mParent;
                    }
                    else
                    {
                        //if we are on the right side of our parent
                        if (x == x.mParent.mRight)
                        {
                            //Move up to our parent
                            x = x.mParent;
                            LeftRotate(x);
                        }

                        /* make our parent black */
                        x.mParent.mColor = RBTreeColor.Black;
                        /* make our grandparent red */
                        x.mParent.mParent.mColor = RBTreeColor.Red;
                        /* right rotate our grandparent */
                        RightRotate(x.mParent.mParent);
                    }
                }
                else
                {
                    //everything here is the same as above, but
                    //exchanging left for right
                    y = x.mParent.mParent.mLeft;
                    if (y != null && y.mColor == RBTreeColor.Red)
                    {
                        x.mParent.mColor         = RBTreeColor.Black;
                        y.mColor                 = RBTreeColor.Black;
                        x.mParent.mParent.mColor = RBTreeColor.Red;

                        x = x.mParent.mParent;
                    }
                    else
                    {
                        if (x == x.mParent.mLeft)
                        {
                            x = x.mParent;
                            RightRotate(x);
                        }

                        x.mParent.mColor         = RBTreeColor.Black;
                        x.mParent.mParent.mColor = RBTreeColor.Red;
                        LeftRotate(x.mParent.mParent);
                    }
                }
            }
            mRoot.mColor = RBTreeColor.Black;
        }
예제 #17
0
 ///<summary>
 ///Remove all items
 ///</summary>
 public void Clear()
 {
     mRoot  = null;
     mCount = 0;
 }
예제 #18
0
 ///<summary>
 ///Set parent node
 ///</summary>
 internal virtual void SetParent(RBTreeNodeBase <T, P> value)
 {
     mParent = value;
 }
예제 #19
0
 ///<summary>
 ///Set left node
 ///</summary>
 internal virtual void SetLeft(RBTreeNodeBase <T, P> value)
 {
     mLeft = value;
 }
예제 #20
0
 ///<summary>
 ///Set right node
 ///</summary>
 internal virtual void SetRight(RBTreeNodeBase <T, P> value)
 {
     mRight = value;
 }
예제 #21
0
 ///<summary>
 ///Copy from other node
 ///</summary>
 internal override void CopyFrom(RBTreeNodeBase <T, RBOrderedNodeParam> z)
 {
     this.mParam.mRank  = z.mParam.mRank;
     this.mParam.mCount = z.mParam.mCount;
     base.CopyFrom(z);
 }
예제 #22
0
        /// <summary>
        /// Delete the node z, and free up the space
        /// </summary>
        protected virtual void Delete(RBTreeNodeBase <T, P> z)
        {
            RBTreeNodeBase <T, P> x, y;

            if (z.mLeft == null || z.mRight == null)
            {
                y = z;
            }
            else
            {
                y = Successor(z);
            }

            if (y.mLeft != null)
            {
                x = y.mLeft;
            }
            else
            {
                x = y.mRight;
            }

            if (x != null)
            {
                x.SetParent(y.mParent);
            }

            if (y.mParent == null)
            {
                mRoot = x;
            }
            else
            {
                if (y == y.mParent.mLeft)
                {
                    y.mParent.SetLeft(x);
                }
                else
                {
                    y.mParent.SetRight(x);
                }
            }

            if (y != z)
            {
                //we must replace 'z' with 'y' node
                y.CopyFrom(z);

                if (z == mRoot)
                {
                    mRoot = y;
                }

                //we do this all above instead of the following line in original code
                //to provide guarantee of the persistence of the node in the tree
                //z.mKey = y.mKey;
            }

            if (y.mColor == RBTreeColor.Black && x != null)
            {
                DeleteFix(x);
            }
        }
예제 #23
0
        /// <summary>
        /// Restore the reb-black properties after a delete
        /// </summary>
        /// <param name="x"></param>
        protected void DeleteFix(RBTreeNodeBase <T, P> x)
        {
            RBTreeNodeBase <T, P> w;

            while (x != mRoot && x.mColor == RBTreeColor.Black)
            {
                if (x == x.mParent.mLeft)
                {
                    w = x.mParent.mRight;
                    if (w == null)
                    {
                        x = x.mParent;
                        continue;
                    }


                    if (w.mColor == RBTreeColor.Red)
                    {
                        w.mColor         = RBTreeColor.Black;
                        x.mParent.mColor = RBTreeColor.Red;
                        LeftRotate(x.mParent);
                        w = x.mParent.mRight;
                    }

                    if (w == null)
                    {
                        x = x.mParent;
                        continue;
                    }

                    if ((w.mLeft == null || w.mLeft.mColor == RBTreeColor.Black) &&
                        (w.mRight == null || w.mRight.mColor == RBTreeColor.Black))
                    {
                        w.mColor = RBTreeColor.Red;
                        x        = x.mParent;
                    }
                    else
                    {
                        if (w.mRight == null || w.mRight.mColor == RBTreeColor.Black)
                        {
                            if (w.mLeft != null)
                            {
                                w.mLeft.mColor = RBTreeColor.Black;
                            }
                            w.mColor = RBTreeColor.Red;
                            RightRotate(w);
                            w = x.mParent.mRight;
                        }

                        w.mColor         = x.mParent.mColor;
                        x.mParent.mColor = RBTreeColor.Black;
                        if (w.mRight != null)
                        {
                            w.mRight.mColor = RBTreeColor.Black;
                        }
                        LeftRotate(x.mParent);
                        x = mRoot;
                    }
                }
                else
                {
                    w = x.mParent.mLeft;
                    if (w == null)
                    {
                        x = x.mParent;
                        continue;
                    }

                    if (w.mColor == RBTreeColor.Red)
                    {
                        w.mColor         = RBTreeColor.Black;
                        x.mParent.mColor = RBTreeColor.Red;
                        RightRotate(x.mParent);
                        w = x.mParent.mLeft;
                    }

                    if (w == null)
                    {
                        x = x.mParent;
                        continue;
                    }

                    if ((w.mRight == null || w.mRight.mColor == RBTreeColor.Black) &&
                        (w.mLeft == null || w.mLeft.mColor == RBTreeColor.Black))
                    {
                        w.mColor = RBTreeColor.Red;
                        x        = x.mParent;
                    }
                    else
                    {
                        if (w.mLeft == null || w.mLeft.mColor == RBTreeColor.Black)
                        {
                            if (w.mRight != null)
                            {
                                w.mRight.mColor = RBTreeColor.Black;
                            }
                            w.mColor = RBTreeColor.Red;
                            LeftRotate(w);
                            w = x.mParent.mLeft;
                        }

                        w.mColor         = x.mParent.mColor;
                        x.mParent.mColor = RBTreeColor.Black;
                        if (w.mLeft != null)
                        {
                            w.mLeft.mColor = RBTreeColor.Black;
                        }
                        RightRotate(x.mParent);
                        x = mRoot;
                    }
                }
            }
            x.mColor = RBTreeColor.Black;
        }