コード例 #1
0
ファイル: RedBlackTree.cs プロジェクト: anderscui/cslib
        private RBNode <T> RR(RBNode <T> root)
        {
            RBNode <T> right = root.Right;

            root.Right = right.Left;
            right.Left = root;

            return(right);
        }
コード例 #2
0
ファイル: RedBlackTree.cs プロジェクト: anderscui/cslib
 private void Print(RBNode <T> root)
 {
     if (root.IsNotNull())
     {
         Print(root.Left);
         Console.Write(root.Item + " ");
         Print(root.Right);
     }
 }
コード例 #3
0
ファイル: RedBlackTree.cs プロジェクト: anderscui/cslib
        private RBNode <T> LL(RBNode <T> root)
        {
            RBNode <T> left = root.Left;

            root.Left  = left.Right;
            left.Right = root;

            return(left);
        }
コード例 #4
0
ファイル: RedBlackTree.cs プロジェクト: anderscui/cslib
        private RBNode <T> LR(RBNode <T> root)
        {
            RBNode <T> left  = root.Left;
            RBNode <T> right = left.Right;

            root.Left   = right.Right;
            right.Right = root;
            left.Right  = right.Left;
            right.Left  = left;

            return(right);
        }
コード例 #5
0
ファイル: RedBlackTree.cs プロジェクト: anderscui/cslib
 private void ReplaceChildOfNodeOrRoot(RBNode <T> parent, RBNode <T> child, RBNode <T> newChild)
 {
     if (parent.IsNotNull())
     {
         if (parent.Left == child)
         {
             parent.Left = newChild;
         }
         else
         {
             parent.Right = newChild;
         }
     }
     else
     {
         _head = newChild;
     }
 }
コード例 #6
0
ファイル: RedBlackTree.cs プロジェクト: anderscui/cslib
        public bool Add(T value)
        {
            // for an empty tree, just create a new root node.
            if (IsEmpty)
            {
                _head       = new RBNode <T>(value);
                _head.IsRed = false;

                return(true);
            }

            p = 0;
            RBNode <T> parent = null, current = _head;

            while (current.IsNotNull())
            {
                path[p++] = current;
                if (current.Item.CompareTo(value) == 0)
                {
                    // item exists.
                    return(false);
                }
                parent  = current;
                current = (value.CompareTo(parent.Item) < 0) ? parent.Left : parent.Right;
            }

            // all the new nodes should be RED.
            current       = new RBNode <T>(value);
            current.IsRed = true;
            if (value.CompareTo(parent.Item) < 0)
            {
                parent.Left = current;
            }
            else
            {
                parent.Right = current;
            }

            if (!parent.IsRed)
            {
                return(true);
            }

            path[p] = current;    // get the complete path.
            while ((p -= 2) >= 0) // check grand parent node.
            {
                RBNode <T> grandParent = path[p];
                parent = path[p + 1];
                if (!parent.IsRed)
                {
                    break;
                }
                RBNode <T> uncle = (grandParent.Left == parent) ? grandParent.Right : grandParent.Left;
                current = path[p + 2];
                if (IsRed(uncle))
                {
                    parent.IsRed = false;
                    uncle.IsRed  = false;
                    if (p > 0)
                    {
                        grandParent.IsRed = true;
                    }
                }
                else
                {
                    // if uncle is null or black.
                    RBNode <T> newRoot;
                    if (grandParent.Left == parent)
                    {
                        newRoot = (parent.Left == current) ? LL(grandParent) : LR(grandParent);
                    }
                    else
                    {
                        newRoot = (parent.Right == current) ? RR(grandParent) : RL(grandParent);
                    }
                    grandParent.IsRed = true;
                    newRoot.IsRed     = false;
                    ReplaceChildOfNodeOrRoot((p > 0) ? path[p - 1] : null, grandParent, newRoot);

                    return(true);
                }
            }

            return(true);
        }
コード例 #7
0
ファイル: RedBlackTree.cs プロジェクト: anderscui/cslib
 public RBNode(T item, RBNode <T> leftChild, RBNode <T> rightChild)
 {
     Item  = item;
     Left  = leftChild;
     Right = rightChild;
 }
コード例 #8
0
ファイル: RedBlackTree.cs プロジェクト: anderscui/cslib
 private bool IsNullOrBlack(RBNode <T> node)
 {
     return(node.IsNull() || !node.IsRed);
 }
コード例 #9
0
ファイル: RedBlackTree.cs プロジェクト: anderscui/cslib
 private bool IsBlack(RBNode <T> node)
 {
     return(node.IsNotNull() && !node.IsRed);
 }
コード例 #10
0
ファイル: RedBlackTree.cs プロジェクト: anderscui/cslib
 private bool IsRed(RBNode <T> uncle)
 {
     return(uncle.IsNotNull() && uncle.IsRed);
 }
コード例 #11
0
ファイル: RedBlackTree.cs プロジェクト: anderscui/cslib
        private void RemoveNode(RBNode <T> node)
        {
            RBNode <T> tmp = null; // after the below step, tmp points to the actual node to be deleted;

            if (node.Degree == 2)
            {
                tmp       = node.Left;
                path[++p] = tmp;
                while (tmp.Right != null)
                {
                    tmp       = tmp.Right;
                    path[++p] = tmp;
                }
                node.Item = tmp.Item;
            }
            else
            {
                tmp = node;
            }

            RBNode <T> newTmp = tmp.Left;

            if (newTmp.IsNull())
            {
                newTmp = tmp.Right;
            }

            if (p > 0)
            {
                RBNode <T> parent = path[p - 1];
                if (parent.Left == tmp)
                {
                    parent.Left = newTmp;
                }
                else
                {
                    parent.Right = newTmp;
                }

                // if the deleted is black and its single child is red.
                if (!tmp.IsRed && IsRed(newTmp))
                {
                    newTmp.IsRed = false;
                    return;
                }
            }
            else
            {
                // if delete the root node.
                _head = newTmp;
                if (_head.IsNotNull())
                {
                    _head.IsRed = false;
                }
                return;
            }

            path[p] = newTmp;
            if (IsRed(tmp))
            {
                // if the deleted is red, directly return.
                return;
            }

            // the deleted and its child are both BLACK.
            while (p > 0)
            {
                RBNode <T> current       = path[p];
                RBNode <T> parent        = path[p - 1];
                bool       currentIsLeft = (parent.Left == current);
                RBNode <T> sibling       = currentIsLeft ? parent.Right : parent.Left;
                if (IsRed(sibling))
                {
                    RBNode <T> newRoot;
                    if (currentIsLeft)
                    {
                        newRoot = RR(parent);
                    }
                    else
                    {
                        newRoot = LL(parent);
                    }
                    ReplaceChildOfNodeOrRoot(p > 1 ? path[p - 2] : null, parent, newRoot);
                    sibling.IsRed = false;
                    parent.IsRed  = true;

                    path[p - 1] = newRoot;
                    path[p]     = parent;
                    path[++p]   = current;
                }
                else
                {
                    // black sibling && black sibling-left && black sibling-right
                    if (IsNullOrBlack(sibling.Left) && IsNullOrBlack(sibling.Right))
                    {
                        if (parent.IsRed)
                        {
                            parent.IsRed  = false;
                            sibling.IsRed = true;
                            if (current.IsNotNull())
                            {
                                // TODO: not needed?
                                current.IsRed = false;
                            }
                            break;
                        }
                        else
                        {
                            // current must be black?
                            parent.IsRed = IsRed(current);
                            if (current.IsNotNull())
                            {
                                current.IsRed = false;
                            }
                            sibling.IsRed = true;
                            p--; // continue to backtrack.
                        }
                    }
                    else
                    {
                        RBNode <T> newRoot;
                        if (currentIsLeft)
                        {
                            if (IsRed(sibling.Right))
                            {
                                newRoot             = RR(parent);
                                sibling.Right.IsRed = false;
                            }
                            else
                            {
                                newRoot = RL(parent);
                            }
                        }
                        else
                        {
                            if (IsRed(sibling.Left))
                            {
                                newRoot            = LL(parent);
                                sibling.Left.IsRed = false;
                            }
                            else
                            {
                                newRoot = LR(parent);
                            }
                        }

                        if (current.IsNotNull())
                        {
                            current.IsRed = false;
                        }
                        newRoot.IsRed = parent.IsRed;
                        parent.IsRed  = false;
                        ReplaceChildOfNodeOrRoot(p > 1 ? path[p - 2] : null, parent, newRoot);
                        break;
                    }
                }
            }
        }