/// <summary> /// Crawls the graph set as the graphToCrawl in the constructor, starting with the vertex specified. If the vertex isn't in the graph, the routine is a no-op /// </summary> /// <param name="vertexToStart">The vertex to start the crawl operation.</param> /// <remarks>vertexToStart can't be null, as a graph can't contain null vertices</remarks> protected void Crawl(TVertex vertexToStart) { if (((object)vertexToStart == null) || (!_graphToCrawl.Contains(vertexToStart))) { return; } var verticesProcessed = new Dictionary <TVertex, VertexColor>(); bool firstRun = true; IEnumerable <TVertex> toEnumerate = _graphToCrawl.Vertices; if (_graphToCrawl.IsSynchronized) { // create safe copy to work with. This can be a bit of a problem regarding performance with massive graphs, but toArray is in general rather quick. toEnumerate = GeneralUtils.PerformSyncedAction(() => _graphToCrawl.Vertices.ToArray(), _graphToCrawl.SyncRoot, _graphToCrawl.IsSynchronized); } foreach (TVertex vertex in toEnumerate) { if (_abortCrawl) { break; } TVertex vertexToProcess = vertex; if (firstRun) { // simply use the vertexToStart. As it's being processed right away, any subsequential occurence later on will be a no-op as the vertex has // already been processed. vertexToProcess = vertexToStart; firstRun = false; } if (!verticesProcessed.ContainsKey(vertexToProcess)) { verticesProcessed.Add(vertexToProcess, VertexColor.NotVisited); } if (verticesProcessed[vertexToProcess] != VertexColor.NotVisited) { continue; } // we only get back to this level for tree roots if it's a non-directed graph. If it's a directed graph, we can end up here as well if we moved // into a path to a vertex which has no out-going edges. if (!_graphToCrawl.IsDirected) { RootDetected(vertexToProcess); } Visit(vertexToProcess, verticesProcessed, null); } }
/// <summary> /// Crawls the graph set as the graphToCrawl in the constructor, starting with the vertex specified. If the vertex isn't in the graph, the routine is a no-op /// </summary> /// <param name="vertexToStart">The vertex to start the crawl operation.</param> /// <remarks>vertexToStart can't be null, as a graph can't contain null vertices</remarks> protected void Crawl(TVertex vertexToStart) { if (((object)vertexToStart == null) || (!_graphToCrawl.Contains(vertexToStart))) { return; } var verticesProcessed = new Dictionary <TVertex, VertexColor>(); bool firstRun = true; foreach (TVertex vertex in _graphToCrawl.Vertices) { if (_abortCrawl) { break; } TVertex vertexToProcess = vertex; if (firstRun) { // simply use the vertexToStart. As it's being processed right away, any subsequential occurence later on will be a no-op as the vertex has // already been processed. vertexToProcess = vertexToStart; firstRun = false; } if (!verticesProcessed.ContainsKey(vertexToProcess)) { verticesProcessed.Add(vertexToProcess, VertexColor.NotVisited); } if (verticesProcessed[vertexToProcess] != VertexColor.NotVisited) { continue; } // we only get back to this level for tree roots if it's a non-directed graph. If it's a directed graph, we can end up here as well if we moved // into a path to a vertex which has no out-going edges. if (!_graphToCrawl.IsDirected) { RootDetected(vertexToProcess); } Visit(vertexToProcess, verticesProcessed, null); } }