/** * Uses BFS to find all vertices connected to the vertex at the start_index. * * TODO: describe the algorithm * * This is an iterator method that yields the control to the * caller each time a new vertex is visited. * * @param start_index The vertex index where BFS is started from. * * @return An iterator interface type used to iterate over the vertices * produced by the BFS algorithm. * * @note The method returns a vertex index and not the vertex itself. * The caller can use GetVertex() to get access the vertex. * * @throws ArgumentException exception if vertex_index is negative * or greater-or-equal to the number of vertices in the graph. */ public IEnumerable <int> BreadthFirstSearch(int start_index) { if (start_index < 0 || start_index >= Size) { throw new ArgumentException(); } // Tracks which vertices are visited during the BFS search BitArray visited_vertices = new BitArray(Size, false); // Once visited, vertex indices are added to the queue QueueViaLinkedList <int> queue = new QueueViaLinkedList <int>(); // Visit the initial node and add it to the queue yield return(start_index); queue.Enqueue(start_index); visited_vertices[start_index] = true; // BFS algorithm is done once the queue becomes empty while (!queue.IsEmpty()) { for (int column = 0; column < Size; ++column) { if (Edges.EdgeExists(queue.Peak(), column) && !visited_vertices[column]) { // Found an adjacent unvisited vertex. Visit it and push it // to the queue so that its adjecent vertices will be visited // later yield return(column); queue.Enqueue(column); visited_vertices[column] = true; } } // At this point we have visited all the adjecent vertices of // the vertex currently at the head of the queue. Thus, remove // this vertex from the queue so that next iteration will visit // the adjacent vertices of the next vertex in the queue queue.Dequeue(); } }
/** * Finds the shortest path between the vertices at the start_index * and end_index. * * @note Uses the modified BFS algorithm to find the shortest path. * TODO: describe the algorithm. * * @param start_index The index of the start vertex. * @param end_index The index of the end vertex. * * @return A collection of vertex indices tracing the path from the * start_index to end_index, or NULL if these two vertices are * not connected. If start_index == end_index, a collection with a * single element (start_index) is returned. * * @throws ArgumentException exception if start_index or end_index * is negative or greater-or-equal to the number of vertices in the * graph. */ public override ICollection <int> FindShortestPath(int start_index, int end_index) { if (start_index < 0 || start_index >= Size || end_index < 0 || end_index >= Size) { throw new ArgumentException(); } if (start_index == end_index) { // Return a list with the given vertex index return(new LinkedList <int>(new int[] { start_index })); } // Tracks which vertices are visited during the BFS search BitArray visited_vertices = new BitArray(Size, false); // Once visited, vertex indices are added to the queue QueueViaLinkedList <int> queue = new QueueViaLinkedList <int>(); // Each entry prev[i] contain the index of the vertex visited // immediatelly prior to vertex i (or -1 if vertex i is the // very first visited vertex or has not been visited yet) int[] prev = Enumerable.Repeat(-1, Size).ToArray(); // Add the index of the start vertex to the queue queue.Enqueue(start_index); visited_vertices[start_index] = true; // BFS algorithm is done once the queue becomes empty while (!queue.IsEmpty()) { // Remove the vertex whose direct siblings are to be visited // in this iteration int curr_vertex_index = queue.Dequeue(); for (int column = 0; column < Size; ++column) { if (Edges.EdgeExists(curr_vertex_index, column) && !visited_vertices[column]) { // Found an adjacent unvisited vertex. Visit it and push it // to the queue so that its adjecent vertices will be visited // later queue.Enqueue(column); visited_vertices[column] = true; // Mark the vertex that was visisted immediatelly prior // to the current one. prev[column] = curr_vertex_index; if (column == end_index) { // Traced the path to the end vertex. Clear the queue // so that the outer while loop will terminate queue.Clear(); break; } } } } LinkedList <int> shortest_path = null; if (prev[end_index] != -1) { // Trace the path from the vertex at end_index back to the // start_index. This is the shortest path from start_index // to end_index shortest_path = new LinkedList <int>(); int index = end_index; while (index != -1) { shortest_path.AddFirst(index); index = prev[index]; } } return(shortest_path); }