/// <summary> /// Get depth of the tree. /// </summary> /// <typeparam name="T">The type of value the node contains.</typeparam> /// <param name="tree">A tree to calculte depth.</param> /// <returns>The depth of the tree.</returns> /// <exception cref="ArgumentNullException">When <paramref name="tree"/> is <see langword="null"/>.</exception> public static int GetDepth <T>(this ITreeBase <T> tree) { int GetDepthInternal(ITreeBase <T> node, int depth) { int result = depth; foreach (ITreeBase <T> child in node) { int tempDepth = GetDepthInternal(child, depth + 1); if (tempDepth > result) { result = tempDepth; } } return(result); } switch (tree ?? throw ExceptionHelper.ArgumentNull(nameof(tree))) { case IBinaryTree <T> binaryTree: return(GetDepthBinary(binaryTree)); default: return(GetDepthInternal(tree, 1)); } }
/// <summary> /// Initialize an instance of <see cref="MultiMap{TKey1, TKey2}"/>. /// </summary> /// <param name="map">Existed map.</param> /// <param name="comparer1">Comparer of key1.</param> /// <param name="comparer2">Comparer of key2.</param> /// <exception cref="ArgumentNullException">When <paramref name="map"/> is <see langword="null"/>.</exception> public MultiMap(IMultiMap <TKey1, TKey2> map, IEqualityComparer <TKey1> comparer1, IEqualityComparer <TKey2> comparer2) : this(map?.Count ?? 0, comparer1, comparer2) { foreach (var item in map ?? throw ExceptionHelper.ArgumentNull(nameof(map))) { Add(item.Key1, item.Key2); } }
/// <summary> /// Inserts an elenemt with specified key1 and key2. /// </summary> /// <param name="key1">The specified key1.</param> /// <param name="key2">The specified key2.</param> /// <param name="add">Determines whether this is an add method.</param> /// <returns><see langword="true"/> if inserts successfully; otherwise, <see langword="false"/>.</returns> /// <exception cref="ArgumentNullException">When <paramref name="key1"/> or <paramref name="key2"/> is <see langword="null"/> and <paramref name="add"/> is <see langword="true"/>.</exception> /// <exception cref="ArgumentException">When the specified element is existed and <paramref name="add"/> is <see langword="true"/>.</exception> private bool Insert(TKey1 key1, TKey2 key2, bool add) { if (key1 == null) { if (add) { throw ExceptionHelper.ArgumentNull(nameof(key1)); } else { return(false); } } if (key2 == null) { if (add) { throw ExceptionHelper.ArgumentNull(nameof(key2)); } else { return(false); } } if (dic.Contains(key1)) { if (dic[key1].Contains(key2)) { if (add) { throw ExceptionHelper.PairExisted(); } else { return(false); } } else { dic.Add(key1, key2); } } else { dic.Add(key1, key2); } if (rev.Contains(key2)) { rev.Add(key2, key1); } else { rev.Add(key2, key1); } return(true); }
/// <summary> /// Get an <see cref="IEnumerable{T}"/> with order of depth-first-search. /// </summary> /// <typeparam name="T">The type of value the node contains.</typeparam> /// <param name="tree">A tree to enumerate.</param> /// <returns>An <see cref="IEnumerable{T}"/> with order of depth-first-search.</returns> /// <exception cref="ArgumentNullException">When <paramref name="tree"/> is <see langword="null"/>.</exception> public static IEnumerable <ITreeBase <T> > AsDFSEnumerable <T>(this ITreeBase <T> tree) { switch (tree ?? throw ExceptionHelper.ArgumentNull(nameof(tree))) { case IBinaryTree <T> binaryTree: return(AsPreOrderEnumerableIterator(binaryTree)); default: return(AsDFSEnumerableIterator(tree)); } }
/// <summary> /// Determines whether the <see cref="MultiMap{TKey1, TKey2}"/> contains the element with specified key1 and key2. /// </summary> /// <param name="key1">The specified key1.</param> /// <param name="key2">The specified key2.</param> /// <returns><see langword="true"/> if it contains; otherwise, <see langword="false"/>.</returns> public bool Contains(TKey1 key1, TKey2 key2) { if (key1 == null) { throw ExceptionHelper.ArgumentNull(nameof(key1)); } if (key2 == null) { throw ExceptionHelper.ArgumentNull(nameof(key2)); } return(dic.Contains(key1) && dic[key1].Contains(key2)); }
/// <summary> /// Get an <see cref="IEnumerable{T}"/> with order of depth-first-search. /// </summary> /// <typeparam name="T">The type of vertex.</typeparam> /// <param name="graph">The graph to enumerate.</param> /// <param name="root">The first vertex to enumerate.</param> /// <returns>An <see cref="IEnumerable{T}"/> with order of depth-first-search.</returns> /// <exception cref="ArgumentNullException">When <paramref name="graph"/> is <see langword="null"/>.</exception> /// <exception cref="KeyNotFoundException">When <paramref name="root"/> is not contained in the graph.</exception> public static IEnumerable <T> AsDFSEnumerable <T>(this IGraph <T> graph, T root) { if (graph == null) { throw ExceptionHelper.ArgumentNull(nameof(graph)); } if (!graph.Contains(root)) { throw ExceptionHelper.KeyNotFound(); } return(AsDFSEnumerableIterator(graph, root)); }
/// <summary> /// Determines whether a vertex is in a loop of an instance of <see cref="IGraph{T}"/>. /// </summary> /// <typeparam name="T">The type of vertex.</typeparam> /// <param name="graph">The graph to enumerate.</param> /// <param name="vertex">The specified vertex.</param> /// <returns><see langword="true"/> if the <paramref name="vertex"/> is in a loop; otherwise, <see langword="false"/>.</returns> /// <exception cref="ArgumentNullException">When <paramref name="graph"/> is <see langword="null"/>.</exception> /// <exception cref="KeyNotFoundException">When <paramref name="vertex"/> is not contained in the graph.</exception> public static bool IsInLoop <T>(this IGraph <T> graph, T vertex) { if (graph == null) { throw ExceptionHelper.ArgumentNull(nameof(graph)); } if (!graph.Contains(vertex)) { throw ExceptionHelper.KeyNotFound(); } Stack <T> nodes = new Stack <T>(); HashSet <T> visited = new HashSet <T>(); nodes.Push(vertex); T last = default; while (nodes.Count != 0) { T current; do { if (nodes.Count == 0) { goto ret; } current = nodes.Pop(); }while (visited.Contains(current)); visited.Add(current); if (graph.TryGetHeads(current, out var heads)) { foreach (var child in heads) { if (!visited.Contains(child)) { nodes.Push(child); } else if (EqualityComparer <T> .Default.Equals(vertex, child) && !EqualityComparer <T> .Default.Equals(last, child)) { return(true); } } } last = current; } ret: return(false); }
/// <summary> /// Copies the entire <see cref="Map{TKey1, TKey2}"/> to a compatible one-dimensional array, starting at the specified index of the target array. /// </summary> /// <param name="array">The one-dimensional <see cref="Array"/> that is the destination of the elements copied from <see cref="Map{TKey1, TKey2}"/>. The <see cref="Array"/> must have zero-based indexing.</param> /// <param name="arrayIndex">The zero-based index in array at which copying begins.</param> /// <exception cref="ArgumentNullException">When <paramref name="array"/> is <see langword="null"/>.</exception> /// <exception cref="ArgumentOutOfRangeException">When <paramref name="arrayIndex"/> is smaller than zero or larger than the length of <paramref name="array"/>.</exception> /// <exception cref="ArgumentException">When <paramref name="array"/> is too small.</exception> public void CopyTo(KeyPair <TKey1, TKey2>[] array, int arrayIndex) { if (array == null) { throw ExceptionHelper.ArgumentNull(nameof(array)); } if (arrayIndex < 0 || arrayIndex > array.Length) { throw ExceptionHelper.ArgumentOutOfRange(nameof(arrayIndex)); } if (array.Length - arrayIndex < dic.Count) { throw ExceptionHelper.ArrayTooSmall(); } foreach (var item in this) { array[arrayIndex++] = item; } }
/// <summary> /// Copies the entire <see cref="Map{TKey1, TKey2}"/> to a compatible one-dimensional array, starting at the specified index of the target array. /// </summary> /// <param name="array">The one-dimensional <see cref="Array"/> that is the destination of the elements copied from <see cref="Map{TKey1, TKey2}"/>. The <see cref="Array"/> must have zero-based indexing.</param> /// <param name="arrayIndex">The zero-based index in array at which copying begins.</param> /// <exception cref="ArgumentNullException">When <paramref name="array"/> is <see langword="null"/>.</exception> /// <exception cref="ArgumentOutOfRangeException">When <paramref name="arrayIndex"/> is smaller than zero or larger than the length of <paramref name="array"/>.</exception> /// <exception cref="ArgumentException">When <paramref name="array"/> is too small.</exception> public void CopyTo(KeyPair <TKey1, TKey2>[] array, int arrayIndex) { if (array == null) { throw ExceptionHelper.ArgumentNull(nameof(array)); } if (arrayIndex < 0 || arrayIndex > array.Length) { throw ExceptionHelper.ArgumentOutOfRange(nameof(arrayIndex)); } if (array.Length - arrayIndex < dic.Count) { throw ExceptionHelper.ArrayTooSmall(); } foreach (var pair in dic) { array[arrayIndex] = new KeyPair <TKey1, TKey2>(pair.Key, pair.Value); arrayIndex++; } }
/// <summary> /// Copies the entire <see cref="Collection{T}"/> to a compatible one-dimensional <see cref="Array"/>, starting at the specified index of the target array. /// </summary> /// <param name="array">The one-dimensional <see cref="Array"/> that is the destination of the elements copied from <see cref="Collection{T}"/>. The <see cref="Array"/> must have zero-based indexing.</param> /// <param name="arrayIndex">The zero-based index in array at which copying begins.</param> public void CopyTo(TElement[] array, int arrayIndex) { if (array == null) { throw ExceptionHelper.ArgumentNull(nameof(array)); } if (arrayIndex < 0) { throw ExceptionHelper.ArgumentOutOfRange(nameof(arrayIndex)); } if (arrayIndex > array.Length) { throw ExceptionHelper.ArgumentOutOfRange(nameof(arrayIndex)); } if (array.Length - arrayIndex < collection.Count) { throw ExceptionHelper.ArrayTooSmall(); } collection.CopyTo(array, arrayIndex); }
/// <summary> /// Initialize a new instance of <see cref="Lookup{TKey, TElement}"/> class. /// </summary> /// <param name="lookup">A lookup source.</param> /// <param name="comparer">The comparer of the keys.</param> public Lookup(ILookup <TKey, TElement> lookup, IEqualityComparer <TKey> comparer) { switch (lookup ?? throw ExceptionHelper.ArgumentNull(nameof(lookup))) { case Lookup <TKey, TElement> lkp: dic = new Dictionary <TKey, Grouping <TKey, TElement> >(lkp.dic, comparer); break; default: dic = new Dictionary <TKey, Grouping <TKey, TElement> >(lookup.Count, comparer); foreach (var grouping in lookup) { foreach (var item in grouping) { Add(grouping.Key, item); } } break; } }
/// <summary> /// Get <see cref="MultiMap{TKey1, TKey2}"/> from <see cref="IEnumerable{TSource}"/>. /// </summary> /// <typeparam name="TSource">Type of elements of <paramref name="source"/>.</typeparam> /// <typeparam name="TKey1">Type of key1.</typeparam> /// <typeparam name="TKey2">Type of key2.</typeparam> /// <param name="source">The source.</param> /// <param name="key1Selector">Selector of key1.</param> /// <param name="key2Selector">Selector of key2.</param> /// <param name="comparer1">Comparer of key1.</param> /// <param name="comparer2">Comparer of key2.</param> /// <returns>An instance of <see cref="MultiMap{TKey1, TKey2}"/>.</returns> /// <exception cref="ArgumentNullException">When <paramref name="source"/> or <paramref name="key1Selector"/> or <paramref name="key2Selector"/> is <see langword="null"/>.</exception> public static MultiMap <TKey1, TKey2> ToMultiMap <TSource, TKey1, TKey2>(this IEnumerable <TSource> source, Func <TSource, TKey1> key1Selector, Func <TSource, TKey2> key2Selector, IEqualityComparer <TKey1> comparer1, IEqualityComparer <TKey2> comparer2) { if (source == null) { throw ExceptionHelper.ArgumentNull(nameof(source)); } if (key1Selector == null) { throw ExceptionHelper.ArgumentNull(nameof(key1Selector)); } if (key2Selector == null) { throw ExceptionHelper.ArgumentNull(nameof(key2Selector)); } MultiMap <TKey1, TKey2> lookup = new MultiMap <TKey1, TKey2>(comparer1, comparer2); foreach (TSource item in source) { lookup.Add(key1Selector(item), key2Selector(item)); } return(lookup); }
public IMapDebugView(IMap <K, V> map) { this.map = map ?? throw ExceptionHelper.ArgumentNull(nameof(map)); }
public ICountableGroupingDebugView(ICountableGrouping <K, V> grouping) { this.grouping = grouping ?? throw ExceptionHelper.ArgumentNull(nameof(grouping)); }
public IMutableLookupDebugView(IMutableLookup <K, V> lookup) { this.lookup = lookup ?? throw ExceptionHelper.ArgumentNull(nameof(lookup)); }