2 using System.Collections;
3 using System.Collections.Generic;
4 using System.Collections.ObjectModel;
8 namespace Mercury.Nucleus.Trees
30 public class Tree<T> : IEquatable<Tree<T>>, IComparable<Tree<T>>,
31 IEnumerable<T>, IEnumerable
35 private string strhash = null;
36 private int? memhash = null;
37 private string memstr = null;
39 internal string CacheKey
40 {
get {
return strhash ?? (strhash = memhash.ToString()); } }
50 : this(value, new List<Tree<T>>())
57 : this(other.Value, other.Children.Concat(children))
73 List<Tree<T>> cld =
new List<Tree<T>>();
74 foreach (var tree
in children)
77 Depth = Math.Max(Depth, tree.Depth + 1);
78 LeavesCount += tree.IsLeaf ? 1 : tree.LeavesCount;
79 NodesCount += tree.NodesCount;
88 public int Depth {
get;
private set; }
91 public int LeavesCount {
get;
private set; }
94 public int NodesCount {
get;
private set; }
97 public T Value {
get;
private set; }
100 public bool IsLeaf {
get {
return Children.Count == 0; } }
104 public IReadOnlyList<Tree<T>> Children {
get;
private set; }
119 public Tree<T> this[
int ix] {
get {
return Children[ix]; } }
128 return tree == null ?
false : Equals(tree);
133 if (memhash.HasValue)
return memhash.Value;
135 int count = Children.Count;
136 memhash = Value.GetHashCode() * (13 * count + 7);
139 for (
int ix = 0; ix < count; ++ix)
141 memhash += (px * (ix + 1)) * Children[ix].GetHashCode();
145 return memhash.Value;
150 if ((maxdepth >= Depth) && (memstr != null))
return memstr;
151 if (IsLeaf)
return Value.ToString();
152 if (maxdepth == 0)
return Value.ToString() +
"{" + LeavesCount.ToString() +
"}";
154 StringBuilder sb =
new StringBuilder();
155 sb.Append(
'[').Append(Value.ToString());
157 for (
int ix = 0; ix < Children.Count; ++ix)
159 var c = (maxdepth < 0) || (maxdepth >= Children[ix].Depth);
160 sb.Append(
' ').Append(Children[ix].ToString(c ? -1 : maxdepth - 1));
165 if (maxdepth >= Depth)
return (memstr = sb.ToString());
166 return sb.ToString();
170 {
return memstr ?? (memstr = this.ToString(-1)); }
176 #region [ IEquatable ]
180 if (other == null)
return false;
181 if (
object.ReferenceEquals(
this, other))
return true;
182 if (this.GetHashCode() != other.
GetHashCode())
return false;
184 bool temp = Value.Equals(other.Value)
185 && Children.Count == other.
Children.Count;
187 for (
int ix = 0; temp && (ix < Children.Count); ++ix)
188 temp = Children[ix].Equals(other.
Children[ix]);
195 #region [ IComparable ]
199 int temp = Comparer<T>.Default.Compare(Value, other.Value);
201 if (temp == 0) temp = Children.Count - other.Children.Count;
203 for (
int ix = 0; (temp == 0) && (ix < Children.Count); ++ix)
204 temp = Children[ix].CompareTo(other.
Children[ix]);
211 #region [ IEnumerable ]
215 IEnumerator IEnumerable.GetEnumerator() {
return DepthFirstEnumerator; }
IEnumerator< T > GetEnumerator()
Tree(Tree< T > other, IEnumerable< Tree< T >> children)
"Copy" constructor
Breadth-First Search tree enumerator
override bool Equals(object obj)
Depth-First Search tree enumerator
Tree(T value)
Initializes a new instance of the Tree{T} class with no child nodes (Leaf)
bool Equals(Tree< T > other)
override string ToString()
int CompareTo(Tree< T > other)
A non-balanced tree implementation that can be referenced from many other trees. Because of that...
string ToString(int maxdepth)
override int GetHashCode()
IReadOnlyList< Tree< T > > Children
Tree's children
Tree(T value, IEnumerable< Tree< T >> children)
Initializes a new instance of the Tree{T} class with the given parent and children ...