示例#1
0
            public bool Contain(T value, out CustomRedBlackTreeNode <T> newNode)
            {
                if (value == null)
                {
                    throw new ArgumentNullException();
                }
                newNode = null;
                CustomRedBlackTreeNode <T> node = mRoot;

                while (node != null)
                {
                    int comparer = mComparer.Compare(value, node.Data);
                    if (comparer > 0)
                    {
                        node = node.RightChild;
                    }
                    else if (comparer < 0)
                    {
                        node = node.LeftChild;
                    }
                    else
                    {
                        newNode = node;
                        return(true);
                    }
                }
                return(false);
            }
示例#2
0
 private CustomRedBlackTreeNode <T> GetMinNode(CustomRedBlackTreeNode <T> node)
 {
     while (node.LeftChild != null)
     {
         node = node.LeftChild;
     }
     return(node);
 }
示例#3
0
 private CustomRedBlackTreeNode <T> DelMin(CustomRedBlackTreeNode <T> node)
 {
     if (node.LeftChild == null)
     {
         return(node.RightChild);
     }
     node.LeftChild = DelMin(node.LeftChild);
     return(node);
 }
示例#4
0
            public T Max()
            {
                CustomRedBlackTreeNode <T> node = mRoot;

                while (node.RightChild != null)
                {
                    node = node.RightChild;
                }
                return(node.Data);
            }
示例#5
0
            private int GetHeight(CustomRedBlackTreeNode <T> root)
            {
                if (root == null)
                {
                    return(0);
                }
                int leftHight  = GetHeight(root.LeftChild);
                int rightHight = GetHeight(root.RightChild);

                return(leftHight > rightHight ? leftHight + 1 : rightHight + 1);
            }
示例#6
0
 private int CountLeafNode(CustomRedBlackTreeNode <T> root)
 {
     if (root == null)
     {
         return(0);
     }
     else
     {
         return(CountLeafNode(root.LeftChild) + CountLeafNode(root.RightChild) + 1);
     }
 }
示例#7
0
 private bool IsBlack(CustomRedBlackTreeNode <T> node)
 {
     if (node == null)
     {
         return(false);
     }
     if (node.Color == BLACK)
     {
         return(true);
     }
     return(false);
 }
示例#8
0
 public T Min()
 {
     if (mRoot != null)
     {
         CustomRedBlackTreeNode <T> node = GetMinNode(mRoot);
         return(node.Data);
     }
     else
     {
         return(default(T));
     }
 }
示例#9
0
 public void Insert(T value)
 {
     if (mRoot == null)
     {
         // 根节点是黑色的
         mRoot = new CustomRedBlackTreeNode <T>(value, BLACK);
     }
     else
     {
         // 新插入节点是红色的
         InsertNode(new CustomRedBlackTreeNode <T>(value, RED), value);
     }
 }
示例#10
0
            // 右旋
            /*************对红黑树节点y进行右旋操作 ******************/

            /*
             * 左旋示意图:对节点y进行右旋
             *        p                   p
             *       /                   /
             *      y                   x
             *     / \                 / \
             *    x  ry               lx  y
             *   / \                     / \
             * lx  rx                   rx ry
             * 右旋做了三件事:
             * 1. 将x的右子节点赋给y的左子节点,并将y赋给x右子节点的父节点(x右子节点非空时)
             * 2. 将y的父节点p(非空时)赋给x的父节点,同时更新p的子节点为x(左或右)
             * 3. 将x的右子节点设为y,将y的父节点设为x
             */
            private void RotateRight(CustomRedBlackTreeNode <T> y)
            {
                //1.将x的右子节点赋值给y的左子节点,同时将y赋值给x的右子节点的父节点(如果x的右子节点非空)
                CustomRedBlackTreeNode <T> x = y.LeftChild;

                y.LeftChild = x.RightChild;

                if (x.RightChild != null)
                {
                    x.RightChild.Parent = y;
                }

                //2.如果y的父节点非空时,将y的父节点赋值给x的父节点,同时更新p的子节点为x
                if (y.Parent != null)
                {
                    x.Parent = y.Parent;
                }
                //如果y的父节点为空,则将x设为父节点
                if (y.Parent == null)
                {
                    mRoot    = x;
                    x.Parent = null;//设置x的父节点为空
                }
                else
                {
                    //如果y是右子节点
                    if (y == y.Parent.RightChild)
                    {
                        //则也将y设为右子节点
                        y.Parent.RightChild = x;
                    }
                    else
                    {
                        //否则将x设为左子节点
                        y.Parent.LeftChild = x;
                    }
                }

                //3.将x的右子节点设为y,y的父节点设置为x
                x.RightChild = y;
                y.Parent     = x;
            }
示例#11
0
            // 左旋转
            /*************对红黑树节点x进行左旋操作 ******************/

            /*
             * 左旋示意图:对节点x进行左旋
             *     p                       p
             *    /                       /
             *   x                       y
             *  / \                     / \
             * lx  y                   x  ry
             *    / \                 / \
             *   ly ry               lx ly
             * 左旋做了三件事:
             * 1. 将y的左子节点赋给x的右子节点,并将x赋给y左子节点的父节点(y左子节点非空时)
             * 2. 将x的父节点p(非空时)赋给y的父节点,同时更新p的子节点为y(左或右)
             * 3. 将y的左子节点设为x,将x的父节点设为y
             */
            private void RotateLeft(CustomRedBlackTreeNode <T> x)
            {
                //1. 将y的左子节点赋给x的右子节点,并将x赋给y左子节点的父节点(y左子节点非空时)
                CustomRedBlackTreeNode <T> y = x.RightChild;

                x.RightChild = y.LeftChild;

                if (y.LeftChild != null)
                {
                    y.LeftChild.Parent = x;
                }

                //2. 将x的父节点p(非空时)赋给y的父节点,同时更新p的子节点为y(左或右)
                if (x.Parent != null)
                {
                    y.Parent = x.Parent;
                }

                if (x.Parent == null)
                {
                    mRoot    = y;    //如果x的父节点为空,则将y设为父节点
                    y.Parent = null; //设置y的父节点为空
                }
                else
                {
                    //如果x是左子节点
                    if (x == x.Parent.LeftChild)
                    {
                        //则也将y设为左子节点
                        x.Parent.LeftChild = y;
                    }
                    else
                    {
                        //否则将y设为右子节点
                        x.Parent.RightChild = y;
                    }
                }

                //3. 将y的左子节点设为x,将x的父节点设为y
                y.LeftChild = x;
                x.Parent    = y;
            }
示例#12
0
            private void InsertNode(CustomRedBlackTreeNode <T> newNode, T value)
            {
                //遍历找到插入位置
                CustomRedBlackTreeNode <T> node = mRoot;
                //插入节点的父节点
                CustomRedBlackTreeNode <T> parent = null;

                while (node != null)
                {
                    parent = node;
                    int comparer = mComparer.Compare(value, node.Data);
                    if (comparer > 0)
                    {
                        node = node.RightChild;
                    }
                    else if (comparer < 0)
                    {
                        node = node.LeftChild;
                    }
                    else
                    {
                        node.Data = value;
                        return;
                    }
                }
                //找到插入位置,设置新插入节点的父节点为current
                newNode.Parent = parent;
                //比较插入节点的值跟插入位置的值的大小, 插入新节点
                int comparer1 = mComparer.Compare(value, parent.Data);

                if (comparer1 > 0)
                {
                    parent.RightChild = newNode;
                }
                else if (comparer1 < 0)
                {
                    parent.LeftChild = newNode;
                }
                //将它重新修整为一颗红黑树
                InsertFixUp(newNode);
            }
示例#13
0
            private void SequentialTraversal(CustomRedBlackTreeNode <T> node)
            {
                if (node == null)
                {
                    return;
                }
                SequentialTraversal(node.LeftChild);
                string nodeColor = node.Color == RED ? "red" : "black";
                string log;

                if (node.Parent != null)
                {
                    log = node.Data + " " + nodeColor + " parent= " + node.Parent.Data;
                }
                else
                {
                    log = node.Data + " " + nodeColor + " parent= null";
                }
                //打印节点数据
                Console.WriteLine(log);
                SequentialTraversal(node.RightChild);
            }
示例#14
0
            private void RemoveFixUp(CustomRedBlackTreeNode <T> node, CustomRedBlackTreeNode <T> parent)
            {
                CustomRedBlackTreeNode <T> brother;

                // 被删除节点的右子树中的最小节点 不是 被删除节点的子节点的情况
                while ((node == null || IsBlack(node)) && (node != mRoot))
                {
                    if (parent.LeftChild == node)
                    {
                        //node是左子节点,下面else与这里的刚好相反
                        brother = parent.RightChild; //node的兄弟节点
                        if (IsRed(brother))
                        {
                            //case1: node的兄弟节点brother是红色的
                            brother.Color = BLACK;
                            parent.Color  = RED;
                            RotateLeft(parent);
                            brother = parent.RightChild;
                        }

                        //case2: node的兄弟节点brother是黑色的,且brother的两个子节点也都是黑色的
                        //继续向上遍历
                        if ((brother.LeftChild == null || IsBlack(brother.LeftChild)) &&
                            (brother.RightChild == null || IsBlack(brother.RightChild)))
                        {
                            //把兄弟节点设置为黑色,平衡红黑树
                            brother.Color = RED;
                            node          = parent;
                            parent        = node.Parent;
                        }
                        else
                        {
                            //case3: node的兄弟节点brother是黑色的,且brother的左子节点是红色,右子节点是黑色
                            if (brother.RightChild == null || IsBlack(brother.RightChild))
                            {
                                brother.LeftChild.Color = BLACK;
                                brother.Color           = RED;
                                RotateRight(brother);
                                brother = parent.RightChild;
                            }

                            //case4: node的兄弟节点brother是黑色的,且brother的右子节点是红色,左子节点任意颜色
                            brother.Color            = parent.Color;
                            parent.Color             = BLACK;
                            brother.RightChild.Color = BLACK;
                            RotateLeft(parent);
                            node = mRoot;
                            break;
                        }
                    }
                    else
                    {
                        //与上面的对称
                        brother = parent.LeftChild;
                        if (IsRed(brother))
                        {
                            // Case 1: node的兄弟brother是红色的
                            brother.Color = BLACK;
                            parent.Color  = RED;
                            RotateRight(parent);
                            brother = parent.LeftChild;
                        }
                        // Case 2: node的兄弟brother是黑色,且brother的俩个子节点都是黑色的
                        if ((brother.LeftChild == null || IsBlack(brother.LeftChild)) &&
                            (brother.RightChild == null || IsBlack(brother.RightChild)))
                        {
                            //把兄弟节点设置为黑色,平衡红黑树
                            brother.Color = RED;
                            node          = parent;
                            parent        = node.Parent;
                        }
                        else
                        {
                            // Case 3: node的兄弟brother是黑色的,并且brother的左子节点是红色,右子节点为黑色。
                            if (brother.LeftChild == null || IsBlack(brother.LeftChild))
                            {
                                brother.RightChild.Color = BLACK;
                                brother.Color            = RED;
                                RotateLeft(brother);
                                brother = parent.LeftChild;
                            }

                            // Case 4: node的兄弟brother是黑色的;并且brother的左子节点是红色的,右子节点任意颜色
                            brother.Color           = parent.Color;
                            parent.Color            = BLACK;
                            brother.LeftChild.Color = BLACK;
                            RotateRight(parent);
                            node = mRoot;
                            break;
                        }
                    }
                }
                //如果删除的最小节点的右子节点是红色,只需要替换最小节点后,涂黑即可
                if (node != null)
                {
                    node.Color = BLACK;
                }
            }
示例#15
0
 public void RemoveMin()
 {
     mRoot = DelMin(mRoot);
 }
示例#16
0
 public void Remove(T value)
 {
     mRoot = RemoveNode(mRoot, value);
 }
示例#17
0
            private CustomRedBlackTreeNode <T> RemoveNode(CustomRedBlackTreeNode <T> node, T value)
            {
                if (node == null)
                {
                    Console.WriteLine("没有找到要删除的节点: " + value);
                    return(null);
                }
                int comparer = mComparer.Compare(value, node.Data);

                if (comparer > 0)
                {
                    node.RightChild = RemoveNode(node.RightChild, value);
                }
                else if (comparer < 0)
                {
                    node.LeftChild = RemoveNode(node.LeftChild, value);
                }
                else
                {
                    // a.如果删除节点没有子节点,直接返回null
                    // b.如果只有一个子节点,返回其子节点代替删除节点即可
                    if (node.LeftChild == null)
                    {
                        if (node.RightChild != null)
                        {
                            node.RightChild.Parent = node.Parent;
                        }
                        return(node.RightChild);
                    }
                    else if (node.RightChild == null)
                    {
                        if (node.LeftChild != null)
                        {
                            node.LeftChild.Parent = node.Parent;
                        }
                        return(node.LeftChild);
                    }
                    else
                    {
                        // c.被删除的节点“左右子节点都不为空”的情况
                        CustomRedBlackTreeNode <T> child;
                        CustomRedBlackTreeNode <T> parent;
                        bool color;
                        // 1. 先找到“删除节点的右子树中的最小节点”,用它来取代被删除节点的位置
                        // 注意:这里也可以选择“删除节点的左子树中的最大节点”作为被删除节点的替换节点
                        CustomRedBlackTreeNode <T> replace = node;
                        replace = GetMinNode(replace.RightChild);

                        // 2. 更新删除父节点及其子节点
                        // 要删除的节点不是根节点
                        if (node.Parent != null)
                        {
                            // 要删除的节点是:删除节点的父节点的左子节点
                            if (node == node.Parent.LeftChild)
                            {
                                // 把“删除节点的右子树中的最小节点”赋值给“删除节点的父节点的左子节点”
                                node.Parent.LeftChild = replace;
                            }
                            else
                            {
                                // 把“删除节点的右子树中的最小节点”赋值给“删除节点的父节点的右子节点”
                                node.Parent.RightChild = replace;
                            }
                        }
                        else
                        {
                            // 要删除的节点是根节点
                            // 如果只有一个根节点,把mRoot赋值为null,这时replace为null
                            // 如果不止一个节点,返回根节点的右子树中的最小节点
                            mRoot = replace;
                        }

                        // 记录被删除节点的右子树中的最小节点的右子节点,父亲节点及颜色,没有左子节点
                        child  = replace.RightChild;
                        parent = replace.Parent;
                        color  = replace.Color;

                        // 3. 删除“被删除节点的右子树中的最小节点”,同时更新替换节点的左右子节点,父亲节点及颜色
                        // 替换节点 也就是 最小节点
                        if (parent == node)
                        {
                            // 被删除节点的右子树中的最小节点是被删除节点的子节点
                            parent = replace;
                        }
                        else
                        {
                            //如果最小节点的右子节点不为空,更新其父节点
                            if (child != null)
                            {
                                child.Parent = parent;
                            }
                            //更新最小节点的父节点的左子节点,指向最小节点的右子节点
                            parent.LeftChild = child;
                            //更新替换节点的右子节点
                            replace.RightChild = node.RightChild;
                            //更新删除节点的右子节点的父节点
                            node.RightChild.Parent = replace;
                        }
                        //更新替换节点的左右子节点,父亲节点及颜色
                        replace.Parent = node.Parent;
                        //保持原来位置的颜色
                        replace.Color     = node.Color;
                        replace.LeftChild = node.LeftChild;
                        //更新删除节点的左子节点的父节点
                        node.LeftChild.Parent = replace;

                        //红黑树平衡修复
                        //如果删除的最小节点颜色是黑色,需要重新平衡红黑树
                        //如果删除的最小节点颜色是红色,只需要替换删除节点后,涂黑即可
                        //上面的保持原来位置的颜色已经处理了这种情况,这里只需要判断最小节点是黑色的情况
                        if (color == BLACK)
                        {
                            //将最小节点的child和parent传进去
                            RemoveFixUp(child, parent);
                        }
                        return(replace);
                    }
                }
                return(node);
            }
示例#18
0
            private void InsertFixUp(CustomRedBlackTreeNode <T> newNode)
            {
                CustomRedBlackTreeNode <T> parent  = newNode.Parent; //插入节点的父节点
                CustomRedBlackTreeNode <T> gParent = null;           //插入节点的祖父节点

                //父节点的颜色是红色,并且不为空
                while (IsRed(parent) && parent != null)
                {
                    //获取祖父节点,这里不用判空,
                    //因为如果祖父节点为空,parent就是根节点,根节点是黑色,不会再次进入循环
                    gParent = parent.Parent;
                    //若父节点是祖父节点的左子节点
                    if (parent == gParent.LeftChild)
                    {
                        CustomRedBlackTreeNode <T> uncle = gParent.RightChild; //获得叔叔节点

                        //case1: 叔叔节点也是红色
                        if (uncle != null && IsRed(uncle))
                        {
                            //把父节点和叔叔节点涂黑,祖父节点涂红
                            parent.Color  = BLACK;
                            uncle.Color   = BLACK;
                            gParent.Color = RED;
                            //把祖父节点作为插入节点,向上继续遍历
                            newNode = gParent;
                            parent  = newNode.Parent;
                            continue; //继续while,重新判断
                        }

                        //case2: 叔叔节点是黑色,且当前节点是右子节点
                        if (newNode == parent.RightChild)
                        {
                            //从父节点处左旋
                            //当这种情况时,只能左旋,因为父亲节点和祖父节点变色,无论左旋还是右旋,都会违背红黑树的基本性质
                            RotateLeft(parent);
                            //当左旋后,红黑树变成case3的情况,区别就是插入节点是父节点
                            //所以,将父节点和插入节点调换一下,为下面右旋做准备
                            CustomRedBlackTreeNode <T> tmp = parent;
                            parent  = newNode;
                            newNode = tmp;
                        }

                        //case3: 叔叔节点是黑色,且当前节点是左子节点
                        // 父亲和祖父节点变色,从祖父节点处右旋
                        parent.Color  = BLACK;
                        gParent.Color = RED;
                        RotateRight(gParent);
                    }
                    else
                    {
                        //若父节点是祖父节点的右子节点,与上面的完全相反
                        CustomRedBlackTreeNode <T> uncle = gParent.LeftChild;

                        //case1: 叔叔节点也是红色
                        if (uncle != null & IsRed(uncle))
                        {
                            //把父节点和叔叔节点涂黑,祖父节点涂红
                            parent.Color  = BLACK;
                            uncle.Color   = BLACK;
                            gParent.Color = RED;
                            //把祖父节点作为插入节点,向上继续遍历
                            newNode = gParent;
                            parent  = newNode.Parent;
                            continue;//继续while,重新判断
                        }

                        //case2: 叔叔节点是黑色的,且当前节点是左子节点
                        if (newNode == parent.LeftChild)
                        {
                            //从父节点处右旋
                            //当这种情况时,只能右旋,因为父亲节点和祖父节点变色,无论左旋还是右旋,都会违背红黑树的基本性质
                            RotateRight(parent);
                            CustomRedBlackTreeNode <T> tmp = parent;
                            parent  = newNode;
                            newNode = tmp;
                        }

                        //case3: 叔叔节点是黑色的,且当前节点是右子节点
                        // 父亲和祖父节点变色,从祖父节点处右旋
                        parent.Color  = BLACK;
                        gParent.Color = RED;
                        RotateLeft(gParent);
                    }
                }
                //将根节点设置为黑色
                mRoot.Color = BLACK;
            }
示例#19
0
 public RedBlackTree()
 {
     mRoot     = null;
     mComparer = Comparer <T> .Default;
 }