diff --git a/DIRECTORY.md b/DIRECTORY.md index b6070388a..76fa1154d 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -73,7 +73,7 @@ * [Line Segment Intersection](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/geometry/line_segment_intersection.cpp) ## Graph - * [Bfs](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/graph/bfs.cpp) + * [Breadth First Search](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/graph/breadth_first_search.cpp) * [Bridge Finding With Tarjan Algorithm](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/graph/bridge_finding_with_tarjan_algorithm.cpp) * [Connected Components](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/graph/connected_components.cpp) * [Connected Components With Dsu](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/graph/connected_components_with_dsu.cpp) diff --git a/graph/bfs.cpp b/graph/bfs.cpp deleted file mode 100644 index 9e66f3ff2..000000000 --- a/graph/bfs.cpp +++ /dev/null @@ -1,196 +0,0 @@ -/** - * - * \file - * \brief [Breadth First Search Algorithm - * (Breadth First Search)](https://en.wikipedia.org/wiki/Breadth-first_search) - * - * \author [Ayaan Khan](http://github.com/ayaankhan98) - * - * \details - * Breadth First Search also quoted as BFS is a Graph Traversal Algorithm. - * Time Complexity O(|V| + |E|) where V are the number of vertices and E - * are the number of edges in the graph. - * - * Applications of Breadth First Search are - * - * 1. Finding shortest path between two vertices say u and v, with path - * length measured by number of edges (an advantage over depth first - * search algorithm) - * 2. Ford-Fulkerson Method for computing the maximum flow in a flow network. - * 3. Testing bipartiteness of a graph. - * 4. Cheney's Algorithm, Copying garbage collection. - * - * And there are many more... - * - *

working

- * In the implementation below we first created a graph using the adjacency - * list representation of graph. - * Breadth First Search Works as follows - * it requires a vertex as a start vertex, Start vertex is that vertex - * from where you want to start traversing the graph. - * we maintain a bool array or a vector to keep track of the vertices - * which we have visited so that we do not traverse the visited vertices - * again and again and eventually fall into an infinite loop. Along with this - * boolen array we use a Queue. - * - * 1. First we mark the start vertex as visited. - * 2. Push this visited vertex in the Queue. - * 3. while the queue is not empty we repeat the following steps - * - * 1. Take out an element from the front of queue - * 2. start exploring the adjacency list of this vertex - * if element in the adjacency list is not visited then we - * push that element into the queue and mark this as visited - * - */ -#include -#include -#include -#include -#include - -/** - * \namespace graph - * \brief Graph algorithms - */ -namespace graph { -/** - * \brief - * Adds and edge between two vertices of graph say u and v in this - * case. - * - * @param adj Adjacency list representation of graph - * @param u first vertex - * @param v second vertex - * - */ -void addEdge(std::vector> *adj, int u, int v) { - /** - * Here we are considering directed graph that's the - * reason we are adding v to the adjacency list representation of u - * but not adding u to the adjacency list representation of v - * - * in case of a un-directed graph you can un comment the statement below. - */ - (*adj)[u - 1].push_back(v - 1); - // adj[v - 1].push_back(u -1); -} - -/** - * \brief - * Function performs the breadth first search algorithm over the graph - * - * @param adj Adjacency list representation of graph - * @param start vertex from where traversing starts - * - */ -std::vector beadth_first_search(const std::vector> &adj, - int start) { - size_t vertices = adj.size(); - - std::vector result; - - /// vector to keep track of visited vertices - std::vector visited(vertices, false); - - std::queue tracker; - /// marking the start vertex as visited - visited[start] = true; - tracker.push(start); - while (!tracker.empty()) { - size_t vertex = tracker.front(); - tracker.pop(); - result.push_back(vertex + 1); - for (auto x : adj[vertex]) { - /// if the vertex is not visited then mark this as visited - /// and push it to the queue - if (!visited[x]) { - visited[x] = true; - tracker.push(x); - } - } - } - return result; -} -} // namespace graph - -void tests() { - std::cout << "Initiating Tests" << std::endl; - - /// Test 1 Begin - std::vector> graphData(4, std::vector()); - graph::addEdge(&graphData, 1, 2); - graph::addEdge(&graphData, 1, 3); - graph::addEdge(&graphData, 2, 3); - graph::addEdge(&graphData, 3, 1); - graph::addEdge(&graphData, 3, 4); - graph::addEdge(&graphData, 4, 4); - - std::vector returnedResult = graph::beadth_first_search(graphData, 2); - std::vector correctResult = {3, 1, 4, 2}; - - assert(std::equal(correctResult.begin(), correctResult.end(), - returnedResult.begin())); - std::cout << "Test 1 Passed..." << std::endl; - - /// Test 2 Begin - /// clear data from previous test - returnedResult.clear(); - correctResult.clear(); - - returnedResult = graph::beadth_first_search(graphData, 0); - correctResult = {1, 2, 3, 4}; - - assert(std::equal(correctResult.begin(), correctResult.end(), - returnedResult.begin())); - std::cout << "Test 2 Passed..." << std::endl; - - /// Test 3 Begins - /// clear data from previous test - graphData.clear(); - returnedResult.clear(); - correctResult.clear(); - - graphData.resize(6); - graph::addEdge(&graphData, 1, 2); - graph::addEdge(&graphData, 1, 3); - graph::addEdge(&graphData, 2, 4); - graph::addEdge(&graphData, 3, 4); - graph::addEdge(&graphData, 2, 5); - graph::addEdge(&graphData, 4, 6); - - returnedResult = graph::beadth_first_search(graphData, 0); - correctResult = {1, 2, 3, 4, 5, 6}; - - assert(std::equal(correctResult.begin(), correctResult.end(), - returnedResult.begin())); - std::cout << "Test 3 Passed..." << std::endl; -} - -/** Main function */ -int main() { - /// running predefined test cases - tests(); - - size_t vertices = 0, edges = 0; - std::cout << "Enter the number of vertices : "; - std::cin >> vertices; - std::cout << "Enter the number of edges : "; - std::cin >> edges; - - /// creating a graph - std::vector> adj(vertices, std::vector()); - - /// taking input for edges - std::cout << "Enter vertices in pair which have edges between them : " - << std::endl; - while (edges--) { - int u = 0, v = 0; - std::cin >> u >> v; - graph::addEdge(&adj, u, v); - } - - /// running Breadth First Search Algorithm on the graph - graph::beadth_first_search(adj, 0); - return 0; -} diff --git a/graph/breadth_first_search.cpp b/graph/breadth_first_search.cpp new file mode 100644 index 000000000..0f4f46160 --- /dev/null +++ b/graph/breadth_first_search.cpp @@ -0,0 +1,184 @@ +/** + * + * \file + * \brief [Breadth First Search Algorithm + * (Breadth First Search)](https://en.wikipedia.org/wiki/Breadth-first_search) + * + * \author [Ayaan Khan](http://github.com/ayaankhan98) + * + * \details + * Breadth First Search also quoted as BFS is a Graph Traversal Algorithm. + * Time Complexity O(|V| + |E|) where V are the number of vertices and E + * are the number of edges in the graph. + * + * Applications of Breadth First Search are + * + * 1. Finding shortest path between two vertices say u and v, with path + * length measured by number of edges (an advantage over depth first + * search algorithm) + * 2. Ford-Fulkerson Method for computing the maximum flow in a flow network. + * 3. Testing bipartiteness of a graph. + * 4. Cheney's Algorithm, Copying garbage collection. + * + * And there are many more... + * + *

working

+ * In the implementation below we first created a graph using the adjacency + * list representation of graph. + * Breadth First Search Works as follows + * it requires a vertex as a start vertex, Start vertex is that vertex + * from where you want to start traversing the graph. + * We maintain a bool array or a vector to keep track of the vertices + * which we have visited so that we do not traverse the visited vertices + * again and again and eventually fall into an infinite loop. Along with this + * boolen array we use a Queue. + * + * 1. First we mark the start vertex as visited. + * 2. Push this visited vertex in the Queue. + * 3. while the queue is not empty we repeat the following steps + * + * 1. Take out an element from the front of queue + * 2. Explore the adjacency list of this vertex + * if element in the adjacency list is not visited then we + * push that element into the queue and mark this as visited + * + */ +#include +#include +#include +#include +#include + +/** + * \namespace graph + * \brief Graph algorithms + */ +namespace graph { +/** + * \brief + * Adds a directed edge from vertex u to vertex v. + * + * @param graph Adjacency list representation of graph + * @param u first vertex + * @param v second vertex + * + */ +void add_directed_edge(std::vector> *graph, int u, int v) { + (*graph)[u].push_back(v); +} + +/** + * \brief + * Adds an undirected edge from vertex u to vertex v. + * Essentially adds too directed edges to the adjacency list reprsentation + * of the graph. + * + * @param graph Adjacency list representation of graph + * @param u first vertex + * @param v second vertex + * + */ +void add_undirected_edge(std::vector> *graph, int u, int v) { + add_directed_edge(graph, u, v); + add_directed_edge(graph, v, u); +} + +/** + * \brief + * Function performs the breadth first search algorithm over the graph + * + * @param graph Adjacency list representation of graph + * @param start vertex from where traversing starts + * @returns a binary vector indicating which vertices were visited during the search. + * + */ +std::vector breadth_first_search(const std::vector> &graph, + int start) { + /// vector to keep track of visited vertices + std::vector visited(graph.size(), false); + /// a queue that stores vertices that need to be further explored + std::queue tracker; + + /// mark the starting vertex as visited + visited[start] = true; + tracker.push(start); + while (!tracker.empty()) { + size_t vertex = tracker.front(); + tracker.pop(); + for (auto x : graph[vertex]) { + /// if the vertex is not visited then mark it as visited + /// and push it to the queue + if (!visited[x]) { + visited[x] = true; + tracker.push(x); + } + } + } + return visited; +} +} // namespace graph + +void tests() { + /// Test 1 Begin + std::vector> graph(4, std::vector()); + graph::add_undirected_edge(&graph, 0, 1); + graph::add_undirected_edge(&graph, 1, 2); + graph::add_undirected_edge(&graph, 2, 3); + + std::vector returned_result = graph::breadth_first_search(graph, 2); + std::vector correct_result = {true, true, true, true}; + + assert(std::equal(correct_result.begin(), correct_result.end(), + returned_result.begin())); + std::cout << "Test 1 Passed..." << std::endl; + + /// Test 2 Begin + returned_result = graph::breadth_first_search(graph, 0); + + assert(std::equal(correct_result.begin(), correct_result.end(), + returned_result.begin())); + std::cout << "Test 2 Passed..." << std::endl; + + /// Test 3 Begins + graph.clear(); + graph.resize(6); + graph::add_directed_edge(&graph, 0, 1); + graph::add_directed_edge(&graph, 0, 2); + graph::add_directed_edge(&graph, 1, 3); + graph::add_directed_edge(&graph, 2, 3); + graph::add_directed_edge(&graph, 1, 4); + graph::add_directed_edge(&graph, 3, 5); + + returned_result = graph::breadth_first_search(graph, 2); + correct_result = {false, false, true, true, false, true}; + + assert(std::equal(correct_result.begin(), correct_result.end(), + returned_result.begin())); + std::cout << "Test 3 Passed..." << std::endl; +} + +/** Main function */ +int main() { + tests(); + + size_t vertices = 0, edges = 0; + std::cout << "Enter the number of vertices: "; + std::cin >> vertices; + std::cout << "Enter the number of edges: "; + std::cin >> edges; + + std::vector> graph(vertices); + + std::cout << "Enter space-separated pairs of vertices that form edges: " + << std::endl; + while (edges--) { + int u = 0, v = 0; + std::cin >> u >> v; + // Decrement the vertex index so that we can read more convenint + // 1-based indexing from the user input. + graph::add_directed_edge(&graph, u - 1, v - 1); + } + + graph::breadth_first_search(graph, 0); + return 0; +}