zoukankan      html  css  js  c++  java
  • 红黑树(RBtree)

    红黑树(RB-Tree)
    结点增加颜色,用非严格的平衡换取增删结点时旋转次数的降低。
    时间复杂度:O(lgn)
    插入、删除效率更高,适用于 STL、Linux进程调度等操作性能稳定的工业级应用。

    红黑树结点

    /// <summary>
    /// 红黑树结点
    /// </summary>
    internal class RBNode<T> : BTNode<T> where T : IComparable<T>
    {
        /// <summary>
        /// 当前父结点
        /// </summary>
        public new RBNode<T> Parent
        {
            get { return (RBNode<T>)base.Parent; }
            set { base.Parent = value; }
        }
        /// <summary>
        /// 左子结点
        /// </summary>
        public new RBNode<T> LeftChild
        {
            get { return (RBNode<T>)base.LeftChild; }
            set { base.LeftChild = value; }
        }
        /// <summary>
        /// 右子结点
        /// </summary>
        public new RBNode<T> RightChild
        {
            get { return (RBNode<T>)base.RightChild; }
            set { base.RightChild = value; }
        }
    
        /// <summary>
        /// 红黑树结点的颜色
        /// </summary>
        public RedBlackTreeColors Color { get; set; }
        /// <summary>
        /// 兄弟结点
        /// </summary>
        public RBNode<T> Sibling
        {
            get => Parent == null ? null : (IsLeftChild ? Parent.RightChild : Parent.LeftChild);
        }
        /// <summary>
        /// 祖父结点
        /// </summary>
        public RBNode<T> GrandParent
        {
            get => Parent == null ? null : Parent.Parent;
        }
    
        /// <summary>
        /// 结点是否为红色,true红色
        /// </summary>
        public bool IsRed { get => Color == RedBlackTreeColors.Red; }
        /// <summary>
        /// 结点是否为黑色,true黑色
        /// </summary>
        public bool IsBlack { get => Color == RedBlackTreeColors.Black; }
    
    
        public RBNode() : this(default, null, null, null) { }
    
        public RBNode(T value) : this(value, null, null, null) { }
        public RBNode(T value, RBNode<T> parent, RBNode<T> left, RBNode<T> right) : base(value, parent, left, right)
        {
            // 新结点初始颜色都为红色
            Color = RedBlackTreeColors.Red;
        }
    
        public override string ToString()
        {
            if (Color == RedBlackTreeColors.Red)
            {
                return $"{Data}о";
            }
            return $"{Data}●";
        }
    }
    
    
    /// <summary>
    /// 红黑树结点颜色类型
    /// </summary>
    enum RedBlackTreeColors
    {
        [Description("红色")]
        Red = 1,
        [Description("黑色")]
        Black = 2,
    };
    

    实现

    
    /// <summary>
    /// 红黑树
    /// </summary>
    public class RedBlackTree<T> : BinarySearchTree<T> where T : IComparable<T>
    {
        /// <summary>
        /// 哨兵
        /// </summary>
        internal readonly RBNode<T> _nIL;
        /// <summary>
        /// 根结点
        /// </summary>
        internal new RBNode<T> Root
        {
            get => (RBNode<T>)base.Root;
            set { base.Root = value; }
        }
        public RedBlackTree() : base()
        {
            _nIL = new RBNode<T>()
            {
                Color = RedBlackTreeColors.Black,
            };
        }
    
        public override void Insert(T item)
        {
            var node = new RBNode<T>(item);
            if (!InsertNode(node))
            {
                throw new InvalidOperationException("树不允许插入重复元素" + item.ToString());
            }
            // 调整树,满足红-黑树的属性 红父 要调整
            InsertFixup(node);
    
            //AdjustTreeAfterInsertion(node);
            //Root.Color = RedBlackTreeColors.Black;
        }
        /*
         不能只是简单的调用基类方法。
        处理过程类似,但是多一些颜色的处理。
         */
        public override void Remove(T item)
        {
            if (IsEmpty)
            {
                throw new Exception("树是空的");
            }
            // TODO 可参考BST删除过程
        }
    
        /// <summary>
        /// 判断结点颜色,true黑色,false红色
        /// </summary>
        /// <param name="node">结点</param>
        /// <returns></returns>
        private bool CheckIsBlack(RBNode<T> node)
        {
            return (node == null                    // 哨兵,叶子结点
                || (node != null && node.IsBlack)); // 内部结点
        }
        /// <summary>
        /// 判断结点颜色,true红色,false黑色
        /// </summary>
        /// <param name="node">结点</param>
        /// <returns></returns>
        private bool CheckIsRed(RBNode<T> node)
        {
            return (node != null && node.IsRed);    // 内部结点才有红色
        }
    }
    

    其他具体实现,同学们可根据红黑树的特点,自行补充完善。

    应用

    public void Test()
    {
        var bst = new BinarySearchTree<int>();
        var rbTree = new RedBlackTree<int>();
        int[] values = new int[] { 11, 2, 14, 1, 7, 15, 5, 8 };
        bst.Insert(values);
    
        WsCommFunc.ConsoleWriteLine(bst.ToString(TraversalMode.LevelOrder));
        Console.WriteLine(TreeDrawer.DrawTree(bst));
        Console.WriteLine("AVL树调整频繁。。。。。。改为红黑树");
    
        rbTree.Clear();
        foreach (var item in values)
        {
            Console.WriteLine("插入 " + item.ToString() + " case1,只变色不旋转");
            rbTree.Insert(item);
            WsCommFunc.ConsoleWriteLine(TreeDrawer.DrawTree(rbTree));
        }
    
        Console.WriteLine("插入 4. case1,case2,case3......");
        rbTree.Insert(4);
        WsCommFunc.ConsoleWriteLine(TreeDrawer.DrawTree(rbTree));
    
    
        Console.WriteLine("Ex2......");
        values = new int[] { 41, 38, 31, 12, 19, 8 };
        rbTree.Clear();
        foreach (var item in values)
        {
            Console.WriteLine("插入 " + item.ToString());
            rbTree.Insert(item);
            WsCommFunc.ConsoleWriteLine(TreeDrawer.DrawTree(rbTree));
        }
    
        Console.WriteLine("删除 8 ");
        rbTree.Remove(8);
        WsCommFunc.ConsoleWriteLine(TreeDrawer.DrawTree(rbTree));
        Console.WriteLine("删除 12 ");
        rbTree.Remove(12);
        WsCommFunc.ConsoleWriteLine(TreeDrawer.DrawTree(rbTree));
        Console.WriteLine("删除 19 ");
        rbTree.Remove(19);
        WsCommFunc.ConsoleWriteLine(TreeDrawer.DrawTree(rbTree));
        Console.WriteLine("删除 31 ");
        rbTree.Remove(31);
        WsCommFunc.ConsoleWriteLine(TreeDrawer.DrawTree(rbTree));
        Console.WriteLine("删除 38 ");
        rbTree.Remove(38);
        WsCommFunc.ConsoleWriteLine(TreeDrawer.DrawTree(rbTree));
        Console.WriteLine("删除 41 ");
        rbTree.Remove(41);
        WsCommFunc.ConsoleWriteLine(TreeDrawer.DrawTree(rbTree));
    
    }
    
  • 相关阅读:
    POJ 2251 Dungeon Master
    POJ1321棋盘问题
    CODE[VS] 1003 电话连线
    CCF-201412-1-门禁系统
    CCF-201412-2-Z字形扫描
    为什么要用补码
    CCF-201409-1-相邻数对
    CCF-201409-2-画图
    CCF-201403-1-相反数
    CCF-201403-2-窗口
  • 原文地址:https://www.cnblogs.com/wesson2019-blog/p/15034770.html
Copyright © 2011-2022 走看看