/// <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);
            }
        }
        /// <summary>
        /// Enumerates vertices 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="exploredSet">The set of explored vertices.</param>
        /// <typeparam name="TExploredSet">The type of the set of explored vertices.</typeparam>
        /// <returns>An enumerator to enumerate the vertices of a depth-first search tree.</returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="graph"/> is <see langword="null"/>,
        /// or <paramref name="exploredSet"/> is <see langword="null"/>.
        /// </exception>
        public IEnumerator <TVertex> EnumerateVertices <TExploredSet>(
            TGraph graph, TVertex source, TExploredSet exploredSet)
            where TExploredSet : ISet <TVertex>
        {
            if (graph == null)
            {
                throw new ArgumentNullException(nameof(graph));
            }

            if (exploredSet == null)
            {
                throw new ArgumentNullException(nameof(exploredSet));
            }

            var stack = new Internal.Stack <TEdgeEnumerator>();

            try
            {
                exploredSet.Add(source);
                yield return(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 TVertex v))
                    {
                        continue;
                    }

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

                    exploredSet.Add(v);
                    yield return(v);

                    stack.Add(graph.EnumerateOutEdges(v));
                }
            }
            finally
            {
                stack.Dispose();
            }
        }
Beispiel #3
0
        private static void TraverseCore <TColorMap, THandler>(TGraph graph, TVertex u, TColorMap colorMap,
                                                               THandler handler, Func <TGraph, TVertex, bool> terminationCondition)
            where TColorMap : IDictionary <TVertex, Color>
            where THandler : IDfsHandler <TGraph, TVertex, TEdge>
        {
            Debug.Assert(graph != null, "graph != null");
            Debug.Assert(colorMap != null, "colorMap != null");
            Debug.Assert(handler != null, "handler != null");
            Debug.Assert(terminationCondition != null, "terminationCondition != null");

            colorMap[u] = Color.Gray;
            handler.OnDiscoverVertex(graph, u);

            if (terminationCondition(graph, u))
            {
                colorMap[u] = Color.Black;
                handler.OnFinishVertex(graph, u);
                return;
            }

            var stack = new Internal.Stack <StackFrame <TVertex, TEdge, TEdgeEnumerator> >();

            try
            {
                TEdgeEnumerator outEdges = graph.EnumerateOutEdges(u);
                stack.Add(new StackFrame <TVertex, TEdge, TEdgeEnumerator>(u, outEdges));

                while (stack.TryTake(out StackFrame <TVertex, TEdge, TEdgeEnumerator> stackFrame))
                {
                    u = stackFrame.Vertex;
                    if (stackFrame.TryGetEdge(out TEdge inEdge))
                    {
                        handler.OnFinishEdge(graph, inEdge);
                    }

                    TEdgeEnumerator edges = stackFrame.EdgeEnumerator;
                    while (edges.MoveNext())
                    {
                        TEdge e = edges.Current;
                        if (!graph.TryGetHead(e, out TVertex v))
                        {
                            continue;
                        }

                        handler.OnExamineEdge(graph, e);
                        Color color = GetColorOrDefault(colorMap, v);
                        if (color == Color.None || color == Color.White)
                        {
                            handler.OnTreeEdge(graph, e);
                            stack.Add(new StackFrame <TVertex, TEdge, TEdgeEnumerator>(u, e, edges));
                            u           = v;
                            colorMap[u] = Color.Gray;
                            handler.OnDiscoverVertex(graph, u);

                            edges = graph.EnumerateOutEdges(u);
                            if (terminationCondition(graph, u))
                            {
                                colorMap[u] = Color.Black;
                                handler.OnFinishVertex(graph, u);
                                return;
                            }
                        }
                        else
                        {
                            if (color == Color.Gray)
                            {
                                handler.OnBackEdge(graph, e);
                            }
                            else
                            {
                                handler.OnForwardOrCrossEdge(graph, e);
                            }
                            handler.OnFinishEdge(graph, e);
                        }
                    }

                    colorMap[u] = Color.Black;
                    handler.OnFinishVertex(graph, u);
                }
            }
            finally
            {
                stack.Dispose();
            }
        }