红黑树(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));

}
原文地址:https://www.cnblogs.com/wesson2019-blog/p/15034770.html