//Iterative depth-first search that returns the node with the target data. public static GraphNode <T> BFS <T>(this SimpleGraph <T> graph, T target) { if (graph == null || graph.Nodes.Count == 0) { return(null); } var visited = new HashSet <GraphNode <T> >(); var queue = new DataStructures.Queue <GraphNode <T> >(); queue.Enqueue(graph.Root); while (!queue.IsEmpty) { GraphNode <T> curr = queue.Dequeue(); if (visited.Contains(curr)) { continue; } if (curr.Data.Equals(target)) { return(curr); } visited.Add(curr); foreach (GraphNode <T> neighbor in curr.Neighbors) { queue.Enqueue(neighbor); } } return(null); }
/// <summary> /// Traverse graph in breadth first order /// Returns traverse path as List /// Time Complexity: O(V+E) /// where V is number of vertices in the graph and E is number of edges in the graph /// </summary> /// <typeparam name="T">Type</typeparam> /// <param name="graph">Graph to be traversed</param> /// <param name="first">start point in graph</param> /// <returns>Traverse path</returns> public static List <T> BreadthFirstSearch <T>(IGraph <T> graph, T first) { List <T> result = new List <T>(); DataStructures.Queue <T> queue = new DataStructures.Queue <T>(); HashSet <T> visited = new HashSet <T>(); queue.Enqueue(first); while (!queue.IsEmpty()) { T current = queue.Dequeue(); result.Add(current); visited.Add(current); foreach (var neighbour in graph.GetNeighbours(current)) { if (!visited.Contains(neighbour)) { queue.Enqueue(neighbour); } } } return(result); }
//Iterative depth-first search that returns the path to the target public static List <GraphNode <T> > BFSPathTo <T>(this SimpleGraph <T> graph, T target) { if (graph == null || graph.Nodes.Count == 0) { return(null); } var visited = new HashSet <GraphNode <T> >(); var queue = new DataStructures.Queue <GraphNode <T> >(); queue.Enqueue(graph.Root); GraphNode <T> curr = null; var path = new List <GraphNode <T> >(); while (!queue.IsEmpty) { curr = queue.Dequeue(); if (visited.Contains(curr)) { continue; } if (curr.Data.Equals(target)) { break; } visited.Add(curr); foreach (GraphNode <T> neighbor in curr.Neighbors) { queue.Enqueue(neighbor); } } if (!curr.Data.Equals(target)) { return(null); } while (curr.Origin != null && !curr.Equals(graph.Root)) { path.Add(curr); curr = curr.Origin; } path.Add(curr); path.Reverse(); return(path); }
public void BreadthFirstSearch(TKey key, ProcessVertex preProcess = null, ProcessVertex postProcess = null) { var v = GetVertex(key); DataStructures.Queue <Vertex> vQueue = new DataStructures.Queue <Vertex>(); v.Viewed = true; vQueue.Enqueue(v); preProcess?.Invoke(v); while (!vQueue.IsEmpty) { foreach (var vert in Nearest(vQueue.Peek().Key).Where(vrt => !vrt.Viewed)) { preProcess?.Invoke(vert); vert.Viewed = true; vQueue.Enqueue(vert); } v = vQueue.Dequeue(); postProcess?.Invoke(v); } }
/// <summary> /// Breadth-First Traversal (traverse nodes closer to the start node before the nodes that are farther). Complexity is linear. /// </summary> /// <param name="startingNode"></param> /// <param name="processNodeAction">Action delegate which is invoked for each node</param> public static void BreadthFirstTraversal(Node <TNodeValue, TLinkProperty> startingNode, Action <Node <TNodeValue, TLinkProperty> > processNodeAction) { if (startingNode == null) { throw new ArgumentNullException("startingNode"); } if (startingNode.Graph == null) { throw new Exception("Node is not associated with a graph"); } var mountedNodes = new Dictionary <Node <TNodeValue, TLinkProperty>, bool>(startingNode.Graph.NodesCount); var queue = new DataStructures.Queue <Node <TNodeValue, TLinkProperty> >(); queue.Enqueue(startingNode); mountedNodes.Add(startingNode, true); while (queue.Count != 0) { var n = queue.Dequeue(); if (processNodeAction != null) { processNodeAction(n); } foreach (var l in n.Links) { if (n == l.Node1 && !mountedNodes.ContainsKey(l.Node2)) { queue.Enqueue(l.Node2); mountedNodes.Add(l.Node2, true); } if (n == l.Node2 && !!mountedNodes.ContainsKey(l.Node1)) { queue.Enqueue(l.Node1); mountedNodes.Add(l.Node1, true); } } } }