예제 #1
0
        /// <summary>
        /// Enumerates edges of the graph in a breadth-first order.
        /// </summary>
        /// <param name="graph">The graph.</param>
        /// <param name="source">The source.</param>
        /// <param name="vertexCount">The number of vertices.</param>
        /// <returns>An enumerator to enumerate the edges of a depth-first search tree.</returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="graph"/> is <see langword="null"/>.
        /// </exception>
        /// <exception cref="ArgumentOutOfRangeException">
        /// <paramref name="vertexCount"/> is less than zero.
        /// </exception>
        public IEnumerator <TEdge> EnumerateEdges(TGraph graph, int source, int vertexCount)
        {
            if (graph == null)
            {
                throw new ArgumentNullException(nameof(graph));
            }

            if (vertexCount < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(vertexCount));
            }

            if (unchecked ((uint)source >= vertexCount))
            {
                yield break;
            }

            byte[] exploredSet = ArrayPool <byte> .Shared.Rent(vertexCount);

            Array.Clear(exploredSet, 0, exploredSet.Length);
            var queue = new Internal.Queue <int>();

            try
            {
                SetHelpers.Add(exploredSet, source);
                queue.Add(source);

                while (queue.TryTake(out int u))
                {
#if DEBUG
                    Debug.Assert(SetHelpers.Contains(exploredSet, u));
#endif
                    TEdgeEnumerator outEdges = graph.EnumerateOutEdges(u);
                    while (outEdges.MoveNext())
                    {
                        TEdge e = outEdges.Current;
                        if (!graph.TryGetHead(e, out int v))
                        {
                            continue;
                        }

                        if (SetHelpers.Contains(exploredSet, v))
                        {
                            continue;
                        }

                        yield return(e);

                        SetHelpers.Add(exploredSet, v);
                        queue.Add(v);
                    }
                }
            }
            finally
            {
                // The Dispose call will happen on the original value of the local if it is the argument to a using statement.
                queue.Dispose();
                ArrayPool <byte> .Shared.Return(exploredSet);
            }
        }
        /// <summary>
        /// Enumerates edges of the graph in a depth-first order starting from the single source.
        /// </summary>
        /// <param name="graph">The graph.</param>
        /// <param name="source">The source.</param>
        /// <param name="vertexCount">The number of vertices.</param>
        /// <returns>An enumerator to enumerate the edges of a depth-first search tree.</returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="graph"/> is <see langword="null"/>.
        /// </exception>
        /// <exception cref="ArgumentOutOfRangeException">
        /// <paramref name="vertexCount"/> is less than zero.
        /// </exception>
        public IEnumerator <TEdge> EnumerateEdges(TGraph graph, int source, int vertexCount)
        {
            if (graph == null)
            {
                throw new ArgumentNullException(nameof(graph));
            }

            if (vertexCount < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(vertexCount));
            }

            if (unchecked ((uint)source >= vertexCount))
            {
                yield break;
            }

            byte[] exploredSet = ArrayPool <byte> .Shared.Rent(vertexCount);

            Array.Clear(exploredSet, 0, exploredSet.Length);
            var stack = new Internal.Stack <TEdgeEnumerator>();

            try
            {
                SetHelpers.Add(exploredSet, source);
                stack.Add(graph.EnumerateOutEdges(source));

                while (stack.TryTake(out TEdgeEnumerator outEdges))
                {
                    if (!outEdges.MoveNext())
                    {
                        continue;
                    }

                    stack.Add(outEdges);

                    TEdge e = outEdges.Current;
                    if (!graph.TryGetHead(e, out int v))
                    {
                        continue;
                    }

                    if (SetHelpers.Contains(exploredSet, v))
                    {
                        continue;
                    }

                    yield return(e);

                    SetHelpers.Add(exploredSet, v);
                    stack.Add(graph.EnumerateOutEdges(v));
                }
            }
            finally
            {
                stack.Dispose();
                ArrayPool <byte> .Shared.Return(exploredSet);
            }
        }