• 二叉树


    二叉树

    本篇纯属娱乐,源于整理代码,发现还曾实现过遍历二叉树。

    虽然.NET/C#中的各种集合类已经实现了最优的排序设计,但了解基本的算法实现有助于软件开发中的各种权衡和选择。
    比如,如果你实现过B+树排序和查找,并将树节点序列化至二进制文件块,则你应该已经了解了各种数据库索引的基本设计。

    什么是二叉树?

    http://en.wikipedia.org/wiki/Binary_tree

    二叉树节点类定义

    View Code
     1   /// <summary>
      2   /// 二叉树节点
      3   /// </summary>
      4   /// <typeparam name="T">The item type</typeparam>
      5   public class BinaryTreeNode<T>
      6   {
      7     #region Constructors
      8 
      9     /// <summary>
     10     /// 二叉树节点
     11     /// </summary>
     12     public BinaryTreeNode()
     13     {
     14     }
     15 
     16     /// <summary>
     17     /// 二叉树节点
     18     /// </summary>
     19     /// <param name="value">节点中的值</param>
     20     public BinaryTreeNode(T value)
     21     {
     22       this.Value = value;
     23     }
     24 
     25     /// <summary>
     26     /// 二叉树节点
     27     /// </summary>
     28     /// <param name="value">节点中的值</param>
     29     /// <param name="parent">节点的父节点</param>
     30     public BinaryTreeNode(T value, BinaryTreeNode<T> parent)
     31     {
     32       this.Value = value;
     33       this.Parent = parent;
     34     }
     35 
     36     /// <summary>
     37     /// 二叉树节点
     38     /// </summary>
     39     /// <param name="value">节点中的值</param>
     40     /// <param name="parent">节点的父节点</param>
     41     /// <param name="left">节点的左节点</param>
     42     /// <param name="right">节点的右节点</param>
     43     public BinaryTreeNode(T value, 
     44       BinaryTreeNode<T> parent, 
     45       BinaryTreeNode<T> left, 
     46       BinaryTreeNode<T> right)
     47     {
     48       this.Value = value;
     49       this.Right = right;
     50       this.Left = left;
     51       this.Parent = parent;
     52     }
     53 
     54     #endregion
     55 
     56     #region Properties
     57 
     58     /// <summary>
     59     /// 节点值
     60     /// </summary>
     61     public T Value { get; set; }
     62 
     63     /// <summary>
     64     /// 父节点
     65     /// </summary>
     66     public BinaryTreeNode<T> Parent { get; set; }
     67 
     68     /// <summary>
     69     /// 左节点
     70     /// </summary>
     71     public BinaryTreeNode<T> Left { get; set; }
     72 
     73     /// <summary>
     74     /// 右节点
     75     /// </summary>
     76     public BinaryTreeNode<T> Right { get; set; }
     77 
     78     /// <summary>
     79     /// 是否为根节点
     80     /// </summary>
     81     public bool IsRoot { get { return Parent == null; } }
     82 
     83     /// <summary>
     84     /// 是否为叶子节点
     85     /// </summary>
     86     public bool IsLeaf { get { return Left == null && Right == null; } }
     87 
     88     /// <summary>
     89     /// 是否为可访问的
     90     /// </summary>
     91     internal bool Visited { get; set; }
     92 
     93     #endregion
     94 
     95     #region Public Overridden Functions
     96 
     97     /// <summary>
     98     /// Returns a <see cref="System.String"/> that represents this instance.
     99     /// </summary>
    100     /// <returns>
    101     /// A <see cref="System.String"/> that represents this instance.
    102     /// </returns>
    103     public override string ToString()
    104     {
    105       return Value.ToString();
    106     }
    107 
    108     #endregion
    109   }

    二叉树类实现

    View Code
    1   /// <summary>
      2   /// 二叉树
      3   /// </summary>
      4   /// <typeparam name="T">二叉树中节点内容类型</typeparam>
      5   [SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix")]
      6   public class BinaryTree<T> : ICollection<T>, IEnumerable<T> where T : IComparable<T>
      7   {
      8     #region Constructor
      9 
     10     /// <summary>
     11     /// 二叉树
     12     /// </summary>
     13     public BinaryTree()
     14     {
     15       NumberOfNodes = 0;
     16     }
     17 
     18     /// <summary>
     19     /// 二叉树
     20     /// </summary>
     21     /// <param name="root">二叉树根节点</param>
     22     public BinaryTree(BinaryTreeNode<T> root)
     23       : this()
     24     {
     25       this.Root = root;
     26     }
     27 
     28     #endregion
     29 
     30     #region Properties
     31 
     32     /// <summary>
     33     /// 树的根节点
     34     /// </summary>
     35     public BinaryTreeNode<T> Root { get; set; }
     36 
     37     /// <summary>
     38     /// 树中节点的数量
     39     /// </summary>
     40     protected int NumberOfNodes { get; set; }
     41 
     42     /// <summary>
     43     /// 树是否为空
     44     /// </summary>
     45     public bool IsEmpty { get { return Root == null; } }
     46 
     47     /// <summary>
     48     /// 获取树中节点的最小值
     49     /// </summary>
     50     public T MinValue
     51     {
     52       get
     53       {
     54         if (IsEmpty)
     55           return default(T);
     56 
     57         BinaryTreeNode<T> minNode = Root;
     58         while (minNode.Left != null)
     59           minNode = minNode.Left;
     60 
     61         return minNode.Value;
     62       }
     63     }
     64 
     65     /// <summary>
     66     /// 获取树中节点的最大值
     67     /// </summary>
     68     public T MaxValue
     69     {
     70       get
     71       {
     72         if (IsEmpty)
     73           return default(T);
     74 
     75         BinaryTreeNode<T> maxNode = Root;
     76         while (maxNode.Right != null)
     77           maxNode = maxNode.Right;
     78 
     79         return maxNode.Value;
     80       }
     81     }
     82 
     83     #endregion
     84 
     85     #region IEnumerable<T> Members
     86 
     87     /// <summary>
     88     /// Returns an enumerator that iterates through the collection.
     89     /// </summary>
     90     /// <returns>
     91     /// A <see cref="T:System.Collections.Generic.IEnumerator`1"></see> 
     92     /// that can be used to iterate through the collection.
     93     /// </returns>
     94     public IEnumerator<T> GetEnumerator()
     95     {
     96       foreach (BinaryTreeNode<T> node in Traverse(Root))
     97       {
     98         yield return node.Value;
     99       }
    100     }
    101 
    102     #endregion
    103 
    104     #region IEnumerable Members
    105 
    106     /// <summary>
    107     /// Returns an enumerator that iterates through a collection.
    108     /// </summary>
    109     /// <returns>
    110     /// An <see cref="T:System.Collections.IEnumerator"/> 
    111     /// object that can be used to iterate through the collection.
    112     /// </returns>
    113     IEnumerator IEnumerable.GetEnumerator()
    114     {
    115       foreach (BinaryTreeNode<T> node in Traverse(Root))
    116       {
    117         yield return node.Value;
    118       }
    119     }
    120 
    121     #endregion
    122 
    123     #region ICollection<T> Members
    124 
    125     /// <summary>
    126     /// 新增节点
    127     /// </summary>
    128     /// <param name="item">The object to add to the 
    129     /// <see cref="T:System.Collections.Generic.ICollection`1"></see>.</param>
    130     /// <exception cref="T:System.NotSupportedException">The 
    131     /// <see cref="T:System.Collections.Generic.ICollection`1"></see> 
    132     /// is read-only.</exception>
    133     public void Add(T item)
    134     {
    135       if (Root == null)
    136       {
    137         Root = new BinaryTreeNode<T>(item);
    138         ++NumberOfNodes;
    139       }
    140       else
    141       {
    142         Insert(item);
    143       }
    144     }
    145 
    146     /// <summary>
    147     /// 清除树
    148     /// </summary>
    149     public void Clear()
    150     {
    151       Root = null;
    152     }
    153 
    154     /// <summary>
    155     /// 树中是否包含此节点
    156     /// </summary>
    157     /// <param name="item">The object to locate in the 
    158     /// <see cref="T:System.Collections.Generic.ICollection`1"></see>.</param>
    159     /// <returns>
    160     /// true if item is found in the 
    161     /// <see cref="T:System.Collections.Generic.ICollection`1"></see>; otherwise, false.
    162     /// </returns>
    163     public bool Contains(T item)
    164     {
    165       if (IsEmpty)
    166         return false;
    167 
    168       BinaryTreeNode<T> currentNode = Root;
    169       while (currentNode != null)
    170       {
    171         int comparedValue = currentNode.Value.CompareTo(item);
    172         if (comparedValue == 0)
    173           return true;
    174         else if (comparedValue < 0)
    175           currentNode = currentNode.Left;
    176         else
    177           currentNode = currentNode.Right;
    178       }
    179 
    180       return false;
    181     }
    182 
    183     /// <summary>
    184     /// 将树中节点拷贝至目标数组
    185     /// </summary>
    186     /// <param name="array">The array.</param>
    187     /// <param name="arrayIndex">Index of the array.</param>
    188     public void CopyTo(T[] array, int arrayIndex)
    189     {
    190       T[] tempArray = new T[NumberOfNodes];
    191       int counter = 0;
    192       foreach (T value in this)
    193       {
    194         tempArray[counter] = value;
    195         ++counter;
    196       }
    197       Array.Copy(tempArray, 0, array, arrayIndex, Count);
    198     }
    199 
    200     /// <summary>
    201     /// 树中节点的数量
    202     /// </summary>
    203     public int Count
    204     {
    205       get { return NumberOfNodes; }
    206     }
    207 
    208     /// <summary>
    209     /// 树是否为只读
    210     /// </summary>
    211     public bool IsReadOnly
    212     {
    213       get { return false; }
    214     }
    215 
    216     /// <summary>
    217     /// 移除节点
    218     /// </summary>
    219     /// <param name="item">节点值</param>
    220     /// <returns>是否移除成功</returns>
    221     public bool Remove(T item)
    222     {
    223       BinaryTreeNode<T> node = Find(item);
    224       if (node == null)
    225         return false;
    226 
    227       List<T> values = new List<T>();
    228       foreach (BinaryTreeNode<T> l in Traverse(node.Left))
    229       {
    230         values.Add(l.Value);
    231       }
    232       foreach (BinaryTreeNode<T> r in Traverse(node.Right))
    233       {
    234         values.Add(r.Value);
    235       }
    236 
    237       if (node.Parent.Left == node)
    238       {
    239         node.Parent.Left = null;
    240       }
    241       else
    242       {
    243         node.Parent.Right = null;
    244       }
    245 
    246       node.Parent = null;
    247 
    248       foreach (T v in values)
    249       {
    250         this.Add(v);
    251       }
    252 
    253       return true;
    254     }
    255 
    256     #endregion
    257 
    258     #region Private Functions
    259 
    260     /// <summary>
    261     /// 查找指定值的节点
    262     /// </summary>
    263     /// <param name="value">指定值</param>
    264     /// <returns>
    265     /// 指定值的节点
    266     /// </returns>
    267     protected BinaryTreeNode<T> Find(T value)
    268     {
    269       foreach (BinaryTreeNode<T> node in Traverse(Root))
    270         if (node.Value.Equals(value))
    271           return node;
    272       return null;
    273     }
    274 
    275     /// <summary>
    276     /// 遍历树
    277     /// </summary>
    278     /// <param name="node">遍历搜索的起始节点</param>
    279     /// <returns>
    280     /// The individual items from the tree
    281     /// </returns>
    282     [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures")]
    283     protected IEnumerable<BinaryTreeNode<T>> Traverse(BinaryTreeNode<T> node)
    284     {
    285       // 遍历左子树
    286       if (node.Left != null)
    287       {
    288         foreach (BinaryTreeNode<T> left in Traverse(node.Left))
    289           yield return left;
    290       }
    291 
    292       // 中序遍历二叉树, 顺序是 左子树,根,右子树
    293       yield return node;
    294 
    295       // 遍历右子树
    296       if (node.Right != null)
    297       {
    298         foreach (BinaryTreeNode<T> right in Traverse(node.Right))
    299           yield return right;
    300       }
    301     }
    302 
    303     /// <summary>
    304     /// 插入节点
    305     /// </summary>
    306     /// <param name="value">插入的节点值</param>
    307     protected void Insert(T value)
    308     {
    309       // 从根节点开始比较
    310       BinaryTreeNode<T> currentNode = Root;
    311       
    312       while (true)
    313       {
    314         if (currentNode == null)
    315           throw new InvalidProgramException("The current tree node cannot be null.");
    316 
    317         // 比较当前节点与新节点的值
    318         int comparedValue = currentNode.Value.CompareTo(value);
    319         if (comparedValue < 0)
    320         {
    321           // 当前节点值小于新节点值
    322           if (currentNode.Left == null)
    323           {
    324             currentNode.Left = new BinaryTreeNode<T>(value, currentNode);
    325             ++NumberOfNodes;
    326             return;
    327           }
    328           else
    329           {
    330             currentNode = currentNode.Left;
    331           }
    332         }
    333         else if (comparedValue > 0)
    334         {
    335           // 当前节点值大于新节点值
    336           if (currentNode.Right == null)
    337           {
    338             currentNode.Right = new BinaryTreeNode<T>(value, currentNode);
    339             ++NumberOfNodes;
    340             return;
    341           }
    342           else
    343           {
    344             currentNode = currentNode.Right;
    345           }
    346         }
    347         else
    348         {
    349           // 当前节点值等于新节点值
    350           currentNode = currentNode.Right;
    351         }
    352       }
    353     }
    354 
    355     #endregion
    356   }

    使用举例

    复制代码
     1   class Program
     2   {
     3     static void Main(string[] args)
     4     {
     5       Console.ForegroundColor = ConsoleColor.Green;
     6 
     7       BinaryTree<string> tree = new BinaryTree<string>();
     8       tree.Add("Dennis");
     9       tree.Add("Gao");
    10       tree.Add("Is");
    11       tree.Add("A");
    12       tree.Add("C#");
    13       tree.Add("Programmer");
    14 
    15       Console.WriteLine("Root Node Is : " + tree.Root.ToString());
    16       Console.WriteLine();
    17 
    18       foreach (var node in tree)
    19       {
    20         Console.WriteLine(node);
    21       }
    22 
    23       Console.ReadKey();
    24     }
    25   }
    复制代码

    中序遍历二叉树

    C#生成MongoDB中的ObjectId

     

    ObjectId介绍

    在MongoDB中,文档(document)在集合(collection)中的存储需要一个唯一的_id字段作为主键。这个_id默认使用ObjectId来定义,因为ObjectId定义的足够短小,并尽最大可能的保持唯一性,同时能被快速的生成。

    ObjectId 是一个 12 Bytes 的 BSON 类型,其包含:

    1. 4 Bytes 自纪元时间开始的秒数
    2. 3 Bytes 机器描述符
    3. 2 Bytes 进程ID
    4. 3 Bytes 随机数

    从定义可以看出,在同一秒内,在不同的机器上相同进程ID条件下,非常有可能生成相同的ObjectId。
    同时可以根据定义判断出,在给定条件下,ObjectId本身即可描述生成的时间顺序

    ObjectId的存储使用Byte数组,而其展现需将Byte数组转换成字符串进行显示,所以通常我们看到的ObjectId都类似于:

    ObjectId("507f191e810c19729de860ea")

    C#定义ObjectId类

    View Code
     1   public class ObjectId
      2   {
      3     private string _string;
      4 
      5     public ObjectId()
      6     {
      7     }
      8 
      9     public ObjectId(string value)
     10       : this(DecodeHex(value))
     11     {
     12     }
     13 
     14     internal ObjectId(byte[] value)
     15     {
     16       Value = value;
     17     }
     18 
     19     public static ObjectId Empty
     20     {
     21       get { return new ObjectId("000000000000000000000000"); }
     22     }
     23 
     24     public byte[] Value { get; private set; }
     25 
     26     public static ObjectId NewObjectId()
     27     {
     28       return new ObjectId { Value = ObjectIdGenerator.Generate() };
     29     }
     30 
     31     public static bool TryParse(string value, out ObjectId objectId)
     32     {
     33       objectId = Empty;
     34       if (value == null || value.Length != 24)
     35       {
     36         return false;
     37       }
     38 
     39       try
     40       {
     41         objectId = new ObjectId(value);
     42         return true;
     43       }
     44       catch (FormatException)
     45       {
     46         return false;
     47       }
     48     }
     49 
     50     protected static byte[] DecodeHex(string value)
     51     {
     52       if (string.IsNullOrEmpty(value))
     53         throw new ArgumentNullException("value");
     54 
     55       var chars = value.ToCharArray();
     56       var numberChars = chars.Length;
     57       var bytes = new byte[numberChars / 2];
     58 
     59       for (var i = 0; i < numberChars; i += 2)
     60       {
     61         bytes[i / 2] = Convert.ToByte(new string(chars, i, 2), 16);
     62       }
     63 
     64       return bytes;
     65     }
     66 
     67     public override int GetHashCode()
     68     {
     69       return Value != null ? ToString().GetHashCode() : 0;
     70     }
     71 
     72     public override string ToString()
     73     {
     74       if (_string == null && Value != null)
     75       {
     76         _string = BitConverter.ToString(Value)
     77           .Replace("-", string.Empty)
     78           .ToLowerInvariant();
     79       }
     80 
     81       return _string;
     82     }
     83 
     84     public override bool Equals(object obj)
     85     {
     86       var other = obj as ObjectId;
     87       return Equals(other);
     88     }
     89 
     90     public bool Equals(ObjectId other)
     91     {
     92       return other != null && ToString() == other.ToString();
     93     }
     94 
     95     public static implicit operator string(ObjectId objectId)
     96     {
     97       return objectId == null ? null : objectId.ToString();
     98     }
     99 
    100     public static implicit operator ObjectId(string value)
    101     {
    102       return new ObjectId(value);
    103     }
    104 
    105     public static bool operator ==(ObjectId left, ObjectId right)
    106     {
    107       if (ReferenceEquals(left, right))
    108       {
    109         return true;
    110       }
    111 
    112       if (((object)left == null) || ((object)right == null))
    113       {
    114         return false;
    115       }
    116 
    117       return left.Equals(right);
    118     }
    119 
    120     public static bool operator !=(ObjectId left, ObjectId right)
    121     {
    122       return !(left == right);
    123     }
    124   }

    C#实现ObjectId的生成器

    View Code
    1   internal static class ObjectIdGenerator
     2   {
     3     private static readonly DateTime Epoch = 
     4       new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
     5     private static readonly object _innerLock = new object();
     6     private static int _counter;
     7     private static readonly byte[] _machineHash = GenerateHostHash();
     8     private static readonly byte[] _processId = 
     9       BitConverter.GetBytes(GenerateProcessId());
    10 
    11     public static byte[] Generate()
    12     {
    13       var oid = new byte[12];
    14       var copyidx = 0;
    15 
    16       Array.Copy(BitConverter.GetBytes(GenerateTime()), 0, oid, copyidx, 4);
    17       copyidx += 4;
    18 
    19       Array.Copy(_machineHash, 0, oid, copyidx, 3);
    20       copyidx += 3;
    21 
    22       Array.Copy(_processId, 0, oid, copyidx, 2);
    23       copyidx += 2;
    24 
    25       Array.Copy(BitConverter.GetBytes(GenerateCounter()), 0, oid, copyidx, 3);
    26 
    27       return oid;
    28     }
    29 
    30     private static int GenerateTime()
    31     {
    32       var now = DateTime.UtcNow;
    33       var nowtime = new DateTime(Epoch.Year, Epoch.Month, Epoch.Day, 
    34         now.Hour, now.Minute, now.Second, now.Millisecond);
    35       var diff = nowtime - Epoch;
    36       return Convert.ToInt32(Math.Floor(diff.TotalMilliseconds));
    37     }
    38 
    39     private static byte[] GenerateHostHash()
    40     {
    41       using (var md5 = MD5.Create())
    42       {
    43         var host = Dns.GetHostName();
    44         return md5.ComputeHash(Encoding.Default.GetBytes(host));
    45       }
    46     }
    47 
    48     private static int GenerateProcessId()
    49     {
    50       var process = Process.GetCurrentProcess();
    51       return process.Id;
    52     }
    53 
    54     private static int GenerateCounter()
    55     {
    56       lock (_innerLock)
    57       {
    58         return _counter++;
    59       }
    60     }
    61   }

    使用举例

    复制代码
     1   class Program
     2   {
     3     static void Main(string[] args)
     4     {
     5       Console.ForegroundColor = ConsoleColor.Red;
     6 
     7       ObjectId emptyOid = ObjectId.Empty;
     8       Console.WriteLine(emptyOid);
     9 
    10       Console.WriteLine();
    11       Console.ForegroundColor = ConsoleColor.Green;
    12 
    13       for (int i = 0; i < 10; i++)
    14       {
    15         ObjectId oid = ObjectId.NewObjectId();
    16         Console.WriteLine(oid);
    17       }
    18 
    19       Console.WriteLine();
    20       Console.ForegroundColor = ConsoleColor.Blue;
    21 
    22       ObjectId existingOid;
    23       ObjectId.TryParse("507f191e810c19729de860ea", out existingOid);
    24       Console.WriteLine(existingOid);
    25 
    26       Console.ReadKey();
    27     }
    28   }
    复制代码

     
     
     
    标签: C#MongoDB
  • 相关阅读:
    图片数据增强
    Crowd Counting using Deep Recurrent Spatial-Aware Network (IJCAI2018)(人群密度)(待补)
    Crowd Counting by Adaptively Fusing Predictions from an Image Pyramid (BMVC2018)
    Top-Down Feedback for Crowd Counting Convolutional Neural Network (AAAI2018) (人群密度)
    [SANet] Scale Aggregation Network for Accurate and Efficient Crowd Counting (ECCV2018)(人群密度)
    Human Protein Atlas Image
    google
    AE(auto encoder)
    feature aggregate
    Arcgis Server api for javascript加载天地图(转)
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3039793.html
Copyright © 2020-2023  润新知