代码拉取完成,页面将自动刷新
/***
* Implements the Depth-First Search algorithm in two ways: Iterative and Recursive.
*
* Provides multiple functions for traversing graphs:
* 1. PrintAll(),
* 2. VisitAll(Action<T> forEachFunc),
* 3. FindFirstMatch(Predicate<T> match).
*
* The VisitAll() applies a function to every graph node. The FindFirstMatch() function searches the graph for a predicate match.
*/
using System;
using System.Collections.Generic;
using DataStructures.Graphs;
namespace Algorithms.Graphs
{
public static class DepthFirstSearcher
{
/// <summary>
/// DFS Recursive Helper function.
/// Visits the neighbors of a given vertex recusively, and applies the given Action<T> to each one of them.
/// </summary>
private static void _visitNeighbors<T>(T Vertex, ref IGraph<T> Graph, ref Dictionary<T, object> Parents, Action<T> Action) where T : IComparable<T>
{
foreach (var adjacent in Graph.Neighbours(Vertex))
{
if (!Parents.ContainsKey(adjacent))
{
// DFS VISIT NODE
Action(adjacent);
// Save adjacents parent into dictionary
Parents.Add(adjacent, Vertex);
// Recusively visit adjacent nodes
_visitNeighbors(adjacent, ref Graph, ref Parents, Action);
}
}
}
/// <summary>
/// Recursive DFS Implementation with helper.
/// Traverses all the nodes in a graph starting from a specific node, applying the passed action to every node.
/// </summary>
public static void VisitAll<T>(ref IGraph<T> Graph, T StartVertex, Action<T> Action) where T : IComparable<T>
{
// Check if graph is empty
if (Graph.VerticesCount == 0)
throw new Exception("Graph is empty!");
// Check if graph has the starting vertex
if (!Graph.HasVertex(StartVertex))
throw new Exception("Starting vertex doesn't belong to graph.");
var parents = new Dictionary<T, object>(Graph.VerticesCount); // keeps track of visited nodes and tree-edges
foreach (var vertex in Graph.Neighbours(StartVertex))
{
if (!parents.ContainsKey(vertex))
{
// DFS VISIT NODE
Action(vertex);
// Add to parents dictionary
parents.Add(vertex, null);
// Visit neighbors using recusrive helper
_visitNeighbors(vertex, ref Graph, ref parents, Action);
}
}
}
/// <summary>
/// Iterative DFS Implementation.
/// Given a starting node, dfs the graph and print the nodes as they get visited.
/// </summary>
public static void PrintAll<T>(IGraph<T> Graph, T StartVertex) where T : IComparable<T>
{
// Check if graph is empty
if (Graph.VerticesCount == 0)
throw new Exception("Graph is empty!");
// Check if graph has the starting vertex
if (!Graph.HasVertex(StartVertex))
throw new Exception("Starting vertex doesn't belong to graph.");
var visited = new HashSet<T>();
var stack = new Stack<T>(Graph.VerticesCount);
stack.Push(StartVertex);
while (stack.Count > 0)
{
var current = stack.Pop();
if (!visited.Contains(current))
{
// DFS VISIT NODE STEP
Console.Write(String.Format("({0}) ", current));
visited.Add(current);
// Get the adjacent nodes of current
foreach (var adjacent in Graph.Neighbours(current))
if (!visited.Contains(adjacent))
stack.Push(adjacent);
}
}
}
/// <summary>
/// Iterative DFS Implementation.
/// Given a predicate function and a starting node, this function searches the nodes of the graph for a first match.
/// </summary>
public static T FindFirstMatch<T>(IGraph<T> Graph, T StartVertex, Predicate<T> Match) where T : IComparable<T>
{
// Check if graph is empty
if (Graph.VerticesCount == 0)
throw new Exception("Graph is empty!");
// Check if graph has the starting vertex
if (!Graph.HasVertex(StartVertex))
throw new Exception("Starting vertex doesn't belong to graph.");
var stack = new Stack<T>();
var parents = new Dictionary<T, object>(Graph.VerticesCount); // keeps track of visited nodes and tree-edges
object currentParent = null;
stack.Push(StartVertex);
while (stack.Count > 0)
{
var current = stack.Pop();
// Skip loop if node was already visited
if (!parents.ContainsKey(current))
{
// Save its parent into the dictionary
// Mark it as visited
parents.Add(current, currentParent);
// DFS VISIT NODE STEP
if (Match(current))
return current;
// Get currents adjacent nodes (might add already visited nodes).
foreach (var adjacent in Graph.Neighbours(current))
if (!parents.ContainsKey(adjacent))
stack.Push(adjacent);
// Mark current as the father of its adjacents. This helps keep track of tree-nodes.
currentParent = current;
}
}//end-while
throw new Exception("Item was not found!");
}
}
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。