/// <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(); } }
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(); } }