/// <summary> /// The algorithm for BFS is almost exactly the same as for DFS except it uses /// a first in, first out (FIFO) queue instead of a stack. /// </summary> /// <typeparam name="TNode"></typeparam> /// <typeparam name="TEdge"></typeparam> /// <param name="graph"></param> /// <param name="source"></param> /// <param name="target"></param> /// <returns></returns> public static SearchResult <TNode, TEdge> SearchBFS <TNode, TEdge>(this SparseGraph <TNode, TEdge> graph, int source, int target = -1) where TNode : GraphNode where TEdge : GraphEdge, new() { // reset search conditions visited = new Visit[graph.NumNodes]; route = Enumerable.Repeat(-1, graph.NumNodes).ToArray(); SearchResult <TNode, TEdge> result = new SearchResult <TNode, TEdge> { Source = source, Target = target }; // Create a queue of edges Queue <TEdge> queue = new Queue <TEdge>(); // create a dummy edge and put on the queue TEdge dummy = new TEdge { From = source, To = source, Cost = 0 }; queue.Enqueue(dummy); //mark the source node as visited visited[source] = Visit.Visited; // while there are edges in the stack keep searching while (queue.Count > 0) { // grab the next edge TEdge next = queue.Dequeue(); // make a note of the parent of the node this edge points to route[next.To] = next.From; // put it on the tree. (making sure the dummy edge is not placed on the tree) if (next != dummy) { result.SpanningTree.Add(next); } // if the target has been found the method can return success if (next.To == target) { result.Found = true; SetPathToTarget(result, source, target); return(result); } // push the edges leading from the node this edge points to onto // the queue (provided the edge does not point to a previously // visited node) foreach (TEdge edge in graph.Edges(next.To)) { if (visited[edge.To] == Visit.Unvisited) { queue.Enqueue(edge); visited[edge.To] = Visit.Visited; } } } // no path to target return(result); }
public static void Print <TNode, TEdge>(this SparseGraph <TNode, TEdge> graph) where TNode : GraphNode where TEdge : GraphEdge, new() { Console.WriteLine($"Graph is directional: {graph.IsDigraph}"); Console.WriteLine($"Graph is empty: {graph.IsEmpty}"); Console.WriteLine($"Next available slot: {graph.NextNodeIndex}"); Console.WriteLine($"Number of nodes: {graph.NumNodes}"); Console.WriteLine($"Number of active nodes: {graph.NumActiveNodes}"); Console.WriteLine($"Number of edges: {graph.NumEdges}"); Console.WriteLine("----------------------------"); Console.WriteLine("Nodes:"); foreach (TNode node in graph.Nodes) { Console.Write($"{node.Index}: "); foreach (TEdge edge in graph.Edges(node.Index)) { Console.WriteLine($"\t{edge.From}->{edge.To}::{edge.Cost}"); } Console.WriteLine(); } Console.WriteLine("----------------------------"); }