< Summary

Information
Class: MoreStructures.DisjointSets.QuickFindDisjointSet
Assembly: MoreStructures
File(s): /home/runner/work/MoreStructures/MoreStructures/MoreStructures/DisjointSets/QuickFindDisjointSet.cs
Line coverage
100%
Covered lines: 42
Uncovered lines: 0
Coverable lines: 42
Total lines: 113
Line coverage: 100%
Branch coverage
100%
Covered branches: 26
Total branches: 26
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity Line coverage
get_SetIds()100%1100%
.ctor(...)100%4100%
get_ValuesCount()100%1100%
get_SetsCount()100%1100%
AreConnected(...)100%10100%
Find(...)100%6100%
Union(...)100%6100%

File(s)

/home/runner/work/MoreStructures/MoreStructures/MoreStructures/DisjointSets/QuickFindDisjointSet.cs

#LineLine coverage
 1namespace MoreStructures.DisjointSets;
 2
 3/// <summary>
 4/// An <see cref="IDisjointSet"/> implementation based on a simple <see cref="List{T}"/> to store set ids of each of
 5/// the values stored in the Disjoint Set.
 6/// </summary>
 7/// <remarks>
 8/// - This implementation optimizes <see cref="Find(int)"/> and <see cref="AreConnected(int, int)"/> runtime, making
 9///   them constant-time operations, at the cost of <see cref="Union(int, int)"/>, which requires a full scan of the
 10///   underlying list and hence is a O(n) operation.
 11///   <br/>
 12/// - Check <see cref="QuickUnionDisjointSet"/> for an alternative implementation of <see cref="IDisjointSet"/> which
 13///   does the opposite, in terms of optimization.
 14/// </remarks>
 15public class QuickFindDisjointSet : IDisjointSet
 16{
 47417    private int[] SetIds { get; }
 18
 19    /// <summary>
 20    /// Builds a Disjoint Set structure containing <paramref name="valuesCount"/> disjoint values, each one into its
 21    /// own singleton set.
 22    /// </summary>
 23    /// <param name="valuesCount"><inheritdoc cref="ValuesCount" path="/summary"/></param>
 24    /// <remarks>
 25    /// Requires initializing all the <paramref name="valuesCount"/> items of the underlying list.
 26    /// <br/>
 27    /// Time and Space Complexity are O(n).
 28    /// </remarks>
 2229    public QuickFindDisjointSet(int valuesCount)
 2230    {
 2231        ValuesCount = valuesCount >= 0
 2232            ? valuesCount
 2233            : throw new ArgumentException("Must be non-negative.", nameof(valuesCount));
 2034        SetIds = new int[valuesCount];
 35
 35636        for (var i = 0; i < ValuesCount; i++)
 15837            SetIds[i] = i;
 2038    }
 39
 40    /// <inheritdoc path="//*[not(self::remarks)]"/>
 41    /// <remarks>
 42    /// Set at construction time, based on the constructor parameter.
 43    /// <br/>
 44    /// Time and Space Complexity are O(1).
 45    /// </remarks>
 61146    public int ValuesCount { get; }
 47
 48    /// <inheritdoc path="//*[not(self::remarks)]"/>
 49    /// <remarks>
 50    /// Obtained as the number of distinct values in the underlying list, which is scanned linearly.
 51    /// <br/>
 52    /// Time Complexity is O(n) and Space Complexity is O(1), where n is <see cref="ValuesCount"/>.
 53    /// </remarks>
 854    public int SetsCount => SetIds.Distinct().Count();
 55
 56    /// <inheritdoc path="//*[not(self::remarks)]"/>
 57    /// <remarks>
 58    /// Calculated in constant-time by comparing the set id of the first value with the set id of the second value.
 59    /// <br/>
 60    /// Time and Space Complexity are O(1).
 61    /// </remarks>
 62    public bool AreConnected(int first, int second)
 2563    {
 2564        if (ValuesCount == 0)
 165            throw new InvalidOperationException(
 166                $"{nameof(AreConnected)} cannot be invoked on an empty queue.");
 2467        if (first < 0 || first >= ValuesCount)
 268            throw new ArgumentException(
 269                $"Must be non-negative and smaller than {nameof(ValuesCount)}.", nameof(first));
 2270        if (second < 0 || second >= ValuesCount)
 271            throw new ArgumentException(
 272                $"Must be non-negative and smaller than {nameof(ValuesCount)}.", nameof(second));
 73
 2074        return SetIds[first] == SetIds[second];
 2075    }
 76
 77    /// <inheritdoc path="//*[not(self::remarks)]"/>
 78    /// <remarks>
 79    /// Calculated in constant-time by retrieving the set id at index <paramref name="value"/> in the underlying list.
 80    /// </remarks>
 81    public int Find(int value)
 8582    {
 8583        if (ValuesCount == 0)
 284            throw new InvalidOperationException(
 285                $"{nameof(AreConnected)} cannot be invoked on an empty queue.");
 8386        if (value < 0 || value >= ValuesCount)
 787            throw new ArgumentException(
 788                $"Must be non-negative and smaller than {nameof(ValuesCount)}.", nameof(value));
 89
 7690        return SetIds[value];
 7691    }
 92
 93    /// <inheritdoc path="//*[not(self::remarks)]"/>
 94    /// <remarks>
 95    /// Retrieves the set id A of <paramref name="first"/> and B of <paramref name="second"/>, via <see cref="Find"/>.
 96    /// <br/>
 97    /// Then replaces all occurrences of B with A, in the underlying list.
 98    /// <br/>
 99    /// Time Complexity is O(n) and Space Complexity is O(1).
 100    /// </remarks>
 101    public void Union(int first, int second)
 28102    {
 28103        var firstSetId = Find(first);
 25104        var secondSetId = Find(second);
 105
 23106        if (firstSetId == secondSetId)
 6107            return;
 108
 374109        for (var i = 0; i < ValuesCount; i++)
 170110            if (SetIds[i] == secondSetId)
 22111                SetIds[i] = firstSetId;
 23112    }
 113}