/** * Gets the weight of the edge between two vertices. * * @param first_index The index of the first vertex. * @param second_index The index of the second vertex. * * @return The weight of the edge. * * @throws ArgumentException exception if first_vertex or second_vertex * is negative or greater-or-equal than the number of vertices in the * graph, or if first_index is equal to second_index. */ public float GetEdgeWeight(int first_index, int second_index) { if (first_index < 0 || first_index >= Size || second_index < 0 || second_index >= Size || !Edges.EdgeExists(first_index, second_index)) { throw new ArgumentException(); } return(Edges.GetEdge(first_index, second_index).Value); }
/** * Finds a minimum spanning tree in the graph. * * The MST is found using a modifed DFS algorithm. The only difference * to the algorithm implemented by DepthFirstSearch() method, is that * here we record the edges that were crossed throughout the algorithm. * These edges make up the MST at the end of the DFS search. * * @param start_index The index of the vertex where search starts at. * @param mst Unweighted tree instance that will become * an MST in this method. The MST instance must * already contain all the original's graph * vertices. * * @return The unweighted graph instance representing the MST. Note * that NULL is returned if there is no path from the vertex at * start_index to one or more vertices in the graph. * * @throws ArgumentException exception if start_index is negative * or greater-or-equal to the number of vertices in the graph. */ protected IUnweightedGraph <VertexT> FindMinimumSpanningTree( int start_index, IUnweightedGraph <VertexT> mst) { if (start_index < 0 || start_index >= Size) { throw new ArgumentException(); } // Tracks the visited vertices so that we don't visit the same // vertex multiple times BitArray visited = new BitArray(Size, false); // After they are visited, the vertices are pushed to the stack // so that search can be continued at them at later time StackViaLinkedList <int> stack = new StackViaLinkedList <int>(); // Push the start vertex to the queue and mark it as visited. stack.Push(start_index); visited[start_index] = true; int added_edges_count = 0; // The column of the adjacency matrix where the search for adjacent // vertices needs to start from. This is set to stack.Pop() + 1 so // that we don't re-scan the entire row of the adjacency matrix // when we continue looking at the adjacent vertices of the vertex // that was pushed to the stack before int column = 0; while (!stack.IsEmpty()) { for (; column < Size; ++column) { if (Edges.EdgeExists(stack.Peak(), column) && !visited[column]) { // Found an unvisited adjacent vertex. Add an edge between // this vertex and the vertex at the top of the stack. // Note that if this is an undirected graph, the AddEdge // method bellow will also add an edge in the opposite // direction. mst.AddEdge(stack.Peak(), column); // Mark it as visited and push it to the stack stack.Push(column); visited[column] = true; ++added_edges_count; // Reset the column to 0 so that the adjacency matrix row // corresponding to unvisited vertex is scanned from the // beginning column = 0; // Break the the loop as we need to look at the adjecent // vertices of the new vertex at the top of the stack next break; } } if (column == Size) { // We've found no unvisited adjecent vertices of the vertex // at the top of the stack. Pop it off the stack so the next // iteration will look at other adjacent vertices of the // new top of the stack. Note that column is set to // stack.Pop() + 1 so we start scanning that vertex's // adjacency matrix row from where we left off column = stack.Pop() + 1; } } // The MST must consists of Size - 1 edges. If this is not the // case, the graph is disconnected and MST doesn't exist (in // which case NULL is returned) return(added_edges_count == Size - 1 ? mst : null); }
/** * 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); }