< Summary

Information
Class: MoreStructures.RecImmTrees.Visitor.FullyRecursiveBreadthFirstTraversal<T1, T2>
Assembly: MoreStructures
File(s): /home/runner/work/MoreStructures/MoreStructures/MoreStructures/RecImmTrees/Visitor/FullyRecursiveBreadthFirstTraversal.cs
Line coverage
100%
Covered lines: 16
Uncovered lines: 0
Coverable lines: 16
Total lines: 103
Line coverage: 100%
Branch coverage
100%
Covered branches: 12
Total branches: 12
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity Line coverage
Visit(...)100%8100%
GetAllVisits()100%4100%

File(s)

/home/runner/work/MoreStructures/MoreStructures/MoreStructures/RecImmTrees/Visitor/FullyRecursiveBreadthFirstTraversal.cs

#LineLine coverage
 1namespace MoreStructures.RecImmTrees.Visitor;
 2
 3/// <inheritdoc cref="BreadthFirstTraversal{TEdge, TNode}" path="//*[not(self::summary or self::remarks)]"/>
 4/// <summary>
 5/// A lazy, fully-recursive, breadth-first <see cref="IVisitStrategy{TNode, TVisitContext}"/> implementation, i.e. a
 6/// traversing strategy which visits all the nodes at the current depth, along any path of the tree, before going
 7/// deeper or shallower, exploring nodes with higher or lower depth.
 8/// </summary>
 9/// <remarks>
 10///     <inheritdoc cref="BreadthFirstTraversal{TEdge, TNode}" path="/remarks"/>
 11///     <para id="advantages">
 12///     ADVANTAGES AND DISADVANTAGES
 13///     <br/>
 14///     Implemented fully recursively, so limited by stack depth and usable with tree of a "reasonable" height.
 15///     </para>
 16/// </remarks>
 17public class FullyRecursiveBreadthFirstTraversal<TEdge, TNode>
 18    : BreadthFirstTraversal<TEdge, TNode>
 19    where TEdge : IRecImmDictIndexedTreeEdge<TEdge, TNode>
 20    where TNode : IRecImmDictIndexedTreeNode<TEdge, TNode>
 21{
 22
 23    /// <inheritdoc
 24    ///     cref="TreeTraversal{TEdge, TNode}.Visit(TNode)"
 25    ///     path="//*[not(self::summary or self::remarks)]" />
 26    /// <summary>
 27    /// <b>Lazily and recursively</b> visits the structure of the provided <paramref name= "node" />, returning the
 28    /// sequence of <see cref="IRecImmDictIndexedTreeNode{TEdge, TNode}"/> of the structure, in breadth-first order.
 29    /// </summary>
 30    /// <remarks>
 31    ///     <inheritdoc cref="FullyRecursiveBreadthFirstTraversal{TEdge, TNode}" path="/remarks"/>
 32    ///     <para id = "algo" >
 33    ///     ALGORITHM
 34    ///     <br/>
 35    ///     - The algorithm first lazily visits all nodes in structure in natural recursion/depth-first order,
 36    ///       returning an <see cref="IEnumerable{T}"/> instance of all nodes with their level in the structure.
 37    ///       <br/>
 38    ///     - Then, it lazily sort and visit them level by level, according to
 39    ///       <see cref="TreeTraversal{TEdge, TNode}.TraversalOrder"/>, yielding to the output sequence, so that the
 40    ///       client code implementing the visitor can lazily process the nodes.
 41    ///     </para>
 42    ///     <para id="complexity">
 43    ///     COMPLEXITY
 44    ///     <br/>
 45    ///     - Excluding visitor, constant time work is done for each of the n nodes of the tree (such as destructuring
 46    ///       of <see cref="IEnumerable{T}"/> items and construction of the input record for the recursive call).
 47    ///       <br/>
 48    ///     - Recursive traversal, as well as sorting, are lazily executed. Iteration-cost is constant w.r.t. n.
 49    ///       <see cref="TreeTraversal{TEdge, TNode}.ChildrenSorter"/> cost depends on the actual algorithm used.
 50    ///       When no sorting, Counting Sort or QuickSort is applied (respectively O(1), O(n), O(n * log(n)), the cost
 51    ///       is tipically equalized or exceeded by sorting cost (see below).
 52    ///       <br/>
 53    ///     - So Time Complexity is dominated by the two operations on the <see cref="IEnumerable{T}"/> generated by
 54    ///       the recursive traversal: sorting and visitor.
 55    ///       <br/>
 56    ///     - Sorting done on the <see cref="IEnumerable{T}"/> of all the n nodes retrieved during recursive traversal
 57    ///       via the LINQ functionalities
 58    ///       <see cref="Enumerable.OrderBy{TSource, TKey}(IEnumerable{TSource}, Func{TSource, TKey})"/> and
 59    ///       <see cref="Enumerable.OrderByDescending{TSource, TKey}(IEnumerable{TSource}, Func{TSource, TKey})"/>.
 60    ///       <br/>
 61    ///     - Visitor is client code invoked during iteration of the output sequence, containing each of the n nodes of
 62    ///       the sorted <see cref="IEnumerable{T}"/>.
 63    ///       <br/>
 64    ///     - If the size of alphabet of elements of the tree is a small constant c, sorting could be done in linear
 65    ///       time via Counting Sort. Otherwise, a comparison-based sorting takes at best a time proportional to
 66    ///       n * log(n). However, LINQ sorting by
 67    ///       <see cref="Enumerable.OrderBy{TSource, TKey}(IEnumerable{TSource}, Func{TSource, TKey})"/> and
 68    ///       <see cref="Enumerable.OrderByDescending{TSource, TKey}(IEnumerable{TSource}, Func{TSource, TKey})"/>
 69    ///       is QuickSort based, and has a O(n * log(n)) average runtime, with O(n^2) worst case.
 70    ///       <br/>
 71    ///     In conclusion:
 72    ///     <br/>
 73    ///     - Time Complexity is O(n * (log(n) + Ts)), where Ts is the amortized time cost of
 74    ///       <see cref="TreeTraversal{TEdge, TNode}.ChildrenSorter"/> per node. Taking into account the visit of
 75    ///       each emitted node, Time Complexity is O(n * (log(n) + Ts + Tv)), where Tv is the time cost of the
 76    ///       visitor per node.
 77    ///       <br/>
 78    ///     - Space Complexity is O(n). Taking into account the visit of each emitted node, Space Complexity is
 79    ///       O(n * Sv), where Sv is the space cost of visitor per node.
 80    ///     </para>
 81    /// </remarks>
 82    public override IEnumerable<TreeTraversalVisit<TEdge, TNode>> Visit(TNode node)
 1583    {
 1584        var visits = GetAllVisits(new(node, default, default, 0));
 1585        return TraversalOrder switch
 1586        {
 10387            TreeTraversalOrder.ParentFirst => visits.OrderBy(nodeWitLevel => nodeWitLevel.Level),
 4588            TreeTraversalOrder.ChildrenFirst => visits.OrderByDescending(nodeWitLevel => nodeWitLevel.Level),
 289            _ => throw new NotSupportedException($"{nameof(TreeTraversalOrder)} {TraversalOrder} is not supported"),
 1590        };
 1391    }
 92
 93    private IEnumerable<TreeTraversalVisit<TEdge, TNode>> GetAllVisits(TreeTraversalVisit<TEdge, TNode> visit)
 13594    {
 13595        yield return visit;
 96
 13597        var (node, _, _, level) = visit;
 98
 64999        foreach (var child in ChildrenSorter(visit))
 848100            foreach (var childVisit in GetAllVisits(new(child.Value, node, child.Key, level + 1)))
 241101                yield return childVisit;
 135102    }
 103}

Methods/Properties

Visit(TNode)
GetAllVisits()