zoukankan      html  css  js  c++  java
  • x01.BSheepTree: 树

    数据结构,无外乎三:

    1. 一对一,线性表,数组是也;

    2. 一对多,树,菜单是也;

    3. 多对多,图,网络是也。

    涉及到树,有一个平衡的问题,左旋转,右旋转,转得人晕晕乎乎。好在陈广的《数据结构C#描述》讲解非常详尽,值得一读。对照该书的例子,采用反编译的手段,写了个小程序,主要的目的是为了学习方便,也便于自己查找复习,无他。源代码可到置顶随笔 x01.Download => book => 2016 中下载:x01.BSheepTree.zip;其运行效果图如下:

               

    略作修改,便成为红黑树,解释参看:红黑树 其运行效果图如下:

               

     关键代码如下:

    /**
     * RedBlackTree.cs (c) 2015 by x01
     */
    using System;
    using System.Diagnostics;
    using System.Text;
    
    namespace x01.BSheepTree
    {
        /// <summary>
        /// Description of RedBlackTree.
        /// </summary>
        public class RedBlackTree : IBinaryTree
        {
            public static readonly bool Red = true;
            public static readonly bool Black = false;
            
            public class RNode : INode
            {
                public int Key { get; set; }
                public int Value { get; set; }
                public RNode Parent { get; set; }
                public RNode Left { get; set; }
                public RNode Right { get; set; }
                public RNode Sibling
                {
                    get {
                        RNode sibling = null;
                        if (Parent != null && this == Parent.Left)
                            sibling = Parent.Right;
                        else if (Parent != null && this == Parent.Right)
                            sibling = Parent.Left;
                        return sibling;
                    }
                }
                public RNode GrandParent
                {
                    get {
                        if (Parent != null)
                            return Parent.Parent;
                        return null;
                    }
                }
                public RNode Uncle
                {
                    get {
                        RNode uncle = null;
                        if (GrandParent != null) {
                            if (Parent == GrandParent.Left)
                                uncle = GrandParent.Right;
                            else if (Parent == GrandParent.Right)
                                uncle = GrandParent.Left;
                        }
                        return uncle;
                    }
                }
                public bool Color { get; set; }
                
                public RNode(int key, int value)
                {
                    this.Key = key;
                    this.Value = value;
                    Color = Red;
                    Parent = Left = Right = null;
                }            
                
                public RNode LeftMost 
                { 
                    get {
                        var node = this;
                        while (node != null && node.Left != null ) {
                            node = node.Left;
                        }
                        return node;
                    }
                }
                
                public int Data {
                    get {
                        return (int)Value;
                    }
                }
                
                INode INode.Left {
                    get {
                        return (INode)Left;
                    }
                }
                
                INode INode.Right {
                    get {
                        return (INode)Right;
                    }
                }
            }
            
            RNode root = null;
            
            public void Insert(int key, int value)
            {
                root = Insert(root, key, value);
                root.Color = Black;
                //SetParent();
            }
            RNode Insert(RNode node, int key, int value)
            {
                if (node == null)
                    return new RNode(key, value);
                int cmp = key.CompareTo(node.Key);
                if (cmp < 0) 
                    node.Left = Insert(node.Left, key, value);
                else if (cmp > 0) 
                    node.Right = Insert(node.Right, key, value);
                else 
                    node.Value = value;
                
                node = Balance(node);
                
                return node;
            }
            
            RNode Balance(RNode node)
            {
                if (node != null) {
                    if (IsRed(node.Right) && !IsRed(node.Left)) node = RotateLeft(node);
                    if (IsRed(node.Left) && IsRed(node.Left.Left)) node = RotateRight(node);
                    if (IsRed(node.Left) && IsRed(node.Right)) FlipColor(node);
                }
                return node;
            }
    
            void SetParent()
            {
                SetParent(root);
            }
            void SetParent(RNode node)
            {
                if (node != null) {
                    if (node.Left != null) { 
                        node.Left.Parent = node;
                        SetParent(node.Left);
                    }
                    if (node.Right != null) {
                        node.Right.Parent = node;
                        SetParent(node.Right);
                    }
                }
            }
            
            void Replace(RNode oldNode, RNode newNode)
            {
                if (oldNode == null || newNode == null)
                    throw new Exception();
                
                oldNode.Key = newNode.Key;
                oldNode.Value = newNode.Value;
            }
            
            public RNode GetNode(int key)
            {
                return GetNode(root, key);
            }
            RNode GetNode(RNode node, int key)
            {
                while (node != null) {
                    int cmp = key.CompareTo(node.Key);
                    if (cmp < 0) node = node.Left;
                    else if (cmp > 0) node = node.Right;
                    else return node;
                }
                return null;
            }
            
            public bool IsEmpty { get { return root == null; } }
            
            public void DeleteMin()
            {
                if (IsEmpty) return;
                if (!IsRed(root.Left) && !IsRed(root.Right))
                    root.Color = Red;
                root = DeleteMin(root);
                if (!IsEmpty) root.Color = Black;
            }
            
            RNode DeleteMin(RNode node)
            {
                if (node != null && node.Left == null) 
                    return null;
                
                if (!IsRed(node.Left) && !IsRed(node.Left.Left))
                    node = MoveRedLeft(node);
                
                node.Left = DeleteMin(node.Left);
                
                return Balance(node);
            }
            
            RNode MoveRedLeft(RNode node)
            {
                FlipColor(node);
                if (IsRed(node.Right.Left)) {
                    node.Right = RotateRight(node.Right);
                    node = RotateLeft(node);
                    FlipColor(node);
                }
                return node;
            }
            
            RNode MoveRedRight(RNode node)
            {
                FlipColor(node);
                if (IsRed(node.Left.Left)) {
                    node = RotateRight(node);
                    FlipColor(node);
                }
                return node;
            }
            
            public void DeleteMax()
            {
                if (IsEmpty) throw new Exception();
                if (!IsRed(root.Left) && !IsRed(root.Right))
                    root.Color = Red;
                root = DeleteMax(root);
                if (!IsEmpty) root.Color = Black;
            }
            
            RNode DeleteMax(RNode node)
            {
                if (IsRed(node.Left))
                    node = RotateRight(node);
                if (node.Right == null)
                    return null;
                if (!IsRed(node.Right) && !IsRed(node.Right.Left))
                    node = MoveRedRight(node);
                node.Right = DeleteMax(node.Right);
                return Balance(node);
            }
            
            public void Delete(int key)
            {
                var node = GetNode(key);
                if (node == null) return;
                
                if (!IsRed(node.Left) && !IsRed(node.Right))
                    root.Color = Red;
                
                root = Delete(root, key);
                if (!IsEmpty) root.Color = Black;
            }
            
            RNode Delete(RNode node, int key)
            {
                if (key.CompareTo(node.Key) < 0) {
                    if (!IsRed(node.Left) && !IsRed(node.Left.Left))
                        node = MoveRedLeft(node);
                    node.Left = Delete(node.Left, key);
                } else {
                    if (IsRed(node.Left))
                        node = RotateRight(node);
                    if (key.CompareTo(node.Key) == 0 && node.Right == null)
                        return null;
                    if (!IsRed(node.Right) && !IsRed(node.Right.Left))
                        node = MoveRedRight(node);
                    if (key.CompareTo(node.Key) == 0) {
                        var x = Min(node.Right);
                        node.Key = x.Key;
                        node.Value = x.Value;
                        node.Right = DeleteMin(node.Right);
                    } else {
                        node.Right = Delete(node.Right, key);
                    }
                }
                return Balance(node);
            }
            
            RNode Min(RedBlackTree.RNode node)
            {
                if (node.Left == null) return node;
                else return Min(node.Left);
            }
            
            void FlipColor(RNode node)
            {
                node.Color = !node.Color;
                node.Left.Color = !node.Left.Color;
                node.Right.Color = !node.Right.Color;
            }
            
            RNode RotateRight(RNode node)
            {
                RNode left = node.Left;
                node.Left = left.Right;
                left.Right = node;
                left.Color = node.Color;
                node.Color = Red;
                return left;
            }
            
            RNode RotateLeft(RNode node)
            {
                RNode right = node.Right;
                node.Right = right.Left;
                right.Left = node;
                right.Color = node.Color;
                node.Color = Red;
                return right;
            }
            
            bool IsRed(RNode node)
            {
                return node != null && node.Color == Red;
            }
            
            public int Count
            {
                get { return _Count(root); }
            }
            int _Count(RNode node)
            {
                if (node != null)
                    return _Count(node.Left) + _Count(node.Right) + 1;
                return 0;
            }
            
            #region Test
            
            void Print()
            {
                Print(root);
            }
            void Print(RNode node)
            {
                if (node != null) {
                    string clr = node.Color ? "R" : "B";
                    Console.Write("{0}{1} => ", node.Key, clr);
                    Print(node.Left);
                    Print(node.Right);
                }
            }
            internal static void Test()
            {
                var tree = new RedBlackTree();
                for (int i = 0; i < 10; i++) {
                    tree.Insert(i,i);
                }
                tree.Delete(7);
                tree.Print();
                Console.WriteLine();
            }
            
            public INode Head {
                get {
                    return (INode)root;
                }
            }
            public bool Add(int data)
            {
                Insert((int)data, (int)data);
                return true;
            }
            public bool Remove(int data)
            {
                Delete((int)data);
                return true;
            }
            
            #endregion
        }
    }
    RedBlackTree.cs
  • 相关阅读:
    js 变量命名规范
    JS
    python 处理中文十六进制的encode %E9%99%88%E8%80%81%E5%B8%88/%E5%9B%BE%E7%89%87
    Pycharm 项目上传至Gitee/Github详细步骤
    Python 类型建议符, Python 定义函数的时候有冒号:
    Python 解析 JSON
    Python 解析 JSON
    Mac 安装 WordPress
    java常用书籍下载
    Docker环境搭建Redis4.0 Cluster
  • 原文地址:https://www.cnblogs.com/china_x01/p/5126305.html
Copyright © 2011-2022 走看看