From b5cbf0e84abc6cda72357be6853ea44dceed7559 Mon Sep 17 00:00:00 2001 From: gpamangkp Date: Wed, 21 Oct 2020 10:25:43 +0530 Subject: [PATCH 1/8] Modified the source for wider range of inputs 1. Replaced the namespace with a generic class Graph 2. Created add edge function to account for both directional and bidirectional graph 3. test case to include string nodes also --- graph/breadth_first_search.cpp | 199 ++++++++++++++++----------------- 1 file changed, 98 insertions(+), 101 deletions(-) diff --git a/graph/breadth_first_search.cpp b/graph/breadth_first_search.cpp index 28cad4930..132687107 100644 --- a/graph/breadth_first_search.cpp +++ b/graph/breadth_first_search.cpp @@ -6,6 +6,7 @@ * * \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 @@ -48,132 +49,127 @@ #include #include #include +#include +#include +#include -/** - * \namespace graph - * \brief Graph algorithms - */ -namespace graph { -/** - * \brief Representation of the graph as an adjacency list. - * - * For every vertex, there is a list of its neighbors in the order in which - * they were added to the graph. By default, the edges are directed, but - * an undirected graph can be represented simply by storing each each as - * two directed edges in both directions. - */ -using adjacency_list = std::vector>; - -/** - * \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(adjacency_list *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(adjacency_list *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 adjacency_list &graph, int start) { - /// vector to keep track of visited vertices - std::vector visited(graph.size(), false); - /// 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); - } - } +/* Class Graph definition */ +template +class Graph{ + /** + * adjacency_list maps every vertex to the list of its neighbours in the order + * in which they are added. + */ + std::map > adjacency_list; + public: + Graph(){}; + void add_edge(T u,T v, bool bidir=true){ + /** + * add_edge(u,v,bidir) is used to add an edge between node u and node v + * by default , bidir is made true , i.e graph is bidirectional . + * It means if edge(u,v) is added then u-->v and v-->u both edges exist. + * + * to make the graph unidirectional pass the third parameter of add_edge as + * false which will + */ + adjacency_list[u].push_back(v); // u-->v edge added + if(bidir==true){ + // if graph is bidirectional + adjacency_list[v].push_back(u); // v-->u edge added + } } - return visited; -} + /** + * this function performs the breadth first search on graph and return a + * mapping which maps the nodes to a boolean value representing whether the + * node was traversed or not. + */ + std::map breadth_first_search(T src){ + std::map tracker; -} // namespace graph + for(auto adjlist: adjacency_list){ + tracker[adjlist.first]=false; + for(auto node:adjacency_list[adjlist.first]){ + tracker[node]=false; + } + } + std::queue q; + q.push(src); + tracker[src]=true; + while(!q.empty()){ + T node = q.front(); + q.pop(); + for(T neighbour : adjacency_list[node]){ + if(!tracker[neighbour]){ + q.push(neighbour); + tracker[neighbour]=true; + } + } + } + return tracker; + } +}; /** Test function */ static void tests() { /// Test 1 Begin - graph::adjacency_list 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); + Graph g; + std::map correct_result; + g.add_edge(0,1); + g.add_edge(1,2); + g.add_edge(2,3); + correct_result[0]=true; + correct_result[1]=true; + correct_result[2]=true; + correct_result[3]=true; - std::vector returned_result = graph::breadth_first_search(graph, 2); - std::vector correct_result = {true, true, true, true}; + std::map returned_result = g.breadth_first_search(2); - assert(std::equal(correct_result.begin(), correct_result.end(), - returned_result.begin())); + assert(returned_result==correct_result); std::cout << "Test 1 Passed..." << std::endl; /// Test 2 Begin - returned_result = graph::breadth_first_search(graph, 0); + returned_result = g.breadth_first_search(0); - assert(std::equal(correct_result.begin(), correct_result.end(), - returned_result.begin())); + assert(returned_result==correct_result); 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); + // 0-> Gorakhpur + // 1-> Lucknow + // 2-> Kanpur + // 3-> Agra + // 4-> Prayagraj + // 5-> Noida + Graph g2; - returned_result = graph::breadth_first_search(graph, 2); - correct_result = {false, false, true, true, false, true}; + g2.add_edge("Gorakhpur","Lucknow",false); + g2.add_edge("Gorakhpur","Kanpur",false); + g2.add_edge("Lucknow","Agra",false); + g2.add_edge("Kanpur","Agra",false); + g2.add_edge("Lucknow","Prayagraj",false); + g2.add_edge("Agra","Noida",false); - assert(std::equal(correct_result.begin(), correct_result.end(), - returned_result.begin())); + std::map correct_res; + std::map returned_res=g2.breadth_first_search("Kanpur"); + correct_res["Gorakhpur"]=false; + correct_res["Lucknow"]=false; + correct_res["Kanpur"]=true; + correct_res["Agra"]=true; + correct_res["Prayagraj"]=false; + correct_res["Noida"]=true; + for(auto x: returned_res){ + std::cout<> vertices; @@ -193,5 +189,6 @@ int main() { } graph::breadth_first_search(graph, 0); +*/ return 0; } From 651c2693175d70e8fca73446152c478302bfacf8 Mon Sep 17 00:00:00 2001 From: Gpamangkp <41160734+Gpamangkp@users.noreply.github.com> Date: Wed, 21 Oct 2020 11:04:34 +0530 Subject: [PATCH 2/8] Modified the code as per the suggestions --- graph/breadth_first_search.cpp | 30 ++++++++---------------------- 1 file changed, 8 insertions(+), 22 deletions(-) diff --git a/graph/breadth_first_search.cpp b/graph/breadth_first_search.cpp index 132687107..f6846e00e 100644 --- a/graph/breadth_first_search.cpp +++ b/graph/breadth_first_search.cpp @@ -87,9 +87,9 @@ class Graph{ std::map breadth_first_search(T src){ std::map tracker; - for(auto adjlist: adjacency_list){ + for(auto const adjlist: adjacency_list){ tracker[adjlist.first]=false; - for(auto node:adjacency_list[adjlist.first]){ + for(auto const node:adjacency_list[adjlist.first]){ tracker[node]=false; } } @@ -99,7 +99,7 @@ class Graph{ while(!q.empty()){ T node = q.front(); q.pop(); - for(T neighbour : adjacency_list[node]){ + for(T const neighbour : adjacency_list[node]){ if(!tracker[neighbour]){ q.push(neighbour); tracker[neighbour]=true; @@ -109,6 +109,7 @@ class Graph{ return tracker; } }; +/* Class definition ends */ /** Test function */ static void tests() { @@ -135,12 +136,6 @@ static void tests() { std::cout << "Test 2 Passed..." << std::endl; /// Test 3 Begins - // 0-> Gorakhpur - // 1-> Lucknow - // 2-> Kanpur - // 3-> Agra - // 4-> Prayagraj - // 5-> Noida Graph g2; g2.add_edge("Gorakhpur","Lucknow",false); @@ -158,9 +153,6 @@ static void tests() { correct_res["Agra"]=true; correct_res["Prayagraj"]=false; correct_res["Noida"]=true; - for(auto x: returned_res){ - std::cout<> vertices; + size_t edges = 0; std::cout << "Enter the number of edges: "; std::cin >> edges; - graph::adjacency_list graph(vertices); + Graph g; 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); + g.add_edge(u,v); } - graph::breadth_first_search(graph, 0); -*/ + g.breadth_first_search(0); return 0; } From 2e5c68a54e8d83c70830d8a78a15e9f175ad95fe Mon Sep 17 00:00:00 2001 From: Gpamangkp <41160734+Gpamangkp@users.noreply.github.com> Date: Wed, 21 Oct 2020 11:09:48 +0530 Subject: [PATCH 3/8] included referenced variable to avoid repitition --- graph/breadth_first_search.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/graph/breadth_first_search.cpp b/graph/breadth_first_search.cpp index f6846e00e..2553efc72 100644 --- a/graph/breadth_first_search.cpp +++ b/graph/breadth_first_search.cpp @@ -87,9 +87,9 @@ class Graph{ std::map breadth_first_search(T src){ std::map tracker; - for(auto const adjlist: adjacency_list){ + for(auto const &adjlist: adjacency_list){ tracker[adjlist.first]=false; - for(auto const node:adjacency_list[adjlist.first]){ + for(auto const &node:adjacency_list[adjlist.first]){ tracker[node]=false; } } @@ -99,7 +99,7 @@ class Graph{ while(!q.empty()){ T node = q.front(); q.pop(); - for(T const neighbour : adjacency_list[node]){ + for(T const &neighbour : adjacency_list[node]){ if(!tracker[neighbour]){ q.push(neighbour); tracker[neighbour]=true; From baffac80ad9d52ddd624b1c01e2d67c085d085a9 Mon Sep 17 00:00:00 2001 From: Gpamangkp <41160734+Gpamangkp@users.noreply.github.com> Date: Fri, 23 Oct 2020 08:30:13 +0530 Subject: [PATCH 4/8] fix : reused the namespace, improved documentation 1. Included the graph definition in the namespace graph 2. Added documentation for the breadth-first search function --- graph/breadth_first_search.cpp | 128 +++++++++++++++++++-------------- 1 file changed, 74 insertions(+), 54 deletions(-) diff --git a/graph/breadth_first_search.cpp b/graph/breadth_first_search.cpp index 2553efc72..f7a0a5077 100644 --- a/graph/breadth_first_search.cpp +++ b/graph/breadth_first_search.cpp @@ -5,6 +5,7 @@ * (Breadth First Search)](https://en.wikipedia.org/wiki/Breadth-first_search) * * \author [Ayaan Khan](http://github.com/ayaankhan98) + * \contributor [Aman Kumar Pandey](http://github.com/gpamangkp) * * * \details @@ -53,68 +54,87 @@ #include #include - -/* Class Graph definition */ -template -class Graph{ - /** - * adjacency_list maps every vertex to the list of its neighbours in the order - * in which they are added. - */ - std::map > adjacency_list; - public: - Graph(){}; - void add_edge(T u,T v, bool bidir=true){ - /** - * add_edge(u,v,bidir) is used to add an edge between node u and node v - * by default , bidir is made true , i.e graph is bidirectional . - * It means if edge(u,v) is added then u-->v and v-->u both edges exist. - * - * to make the graph unidirectional pass the third parameter of add_edge as - * false which will - */ - adjacency_list[u].push_back(v); // u-->v edge added - if(bidir==true){ - // if graph is bidirectional - adjacency_list[v].push_back(u); // v-->u edge added - } - } +///namespace graph which contains the class Graph +namespace graph{ + /* Class Graph definition */ + template + class Graph{ /** - * this function performs the breadth first search on graph and return a - * mapping which maps the nodes to a boolean value representing whether the - * node was traversed or not. + * adjacency_list maps every vertex to the list of its neighbours in the order + * in which they are added. */ - std::map breadth_first_search(T src){ - std::map tracker; - - for(auto const &adjlist: adjacency_list){ - tracker[adjlist.first]=false; - for(auto const &node:adjacency_list[adjlist.first]){ - tracker[node]=false; + std::map > adjacency_list; + public: + Graph(){}; + void add_edge(T u,T v, bool bidir=true){ + /** + * add_edge(u,v,bidir) is used to add an edge between node u and node v + * by default , bidir is made true , i.e graph is bidirectional . + * It means if edge(u,v) is added then u-->v and v-->u both edges exist. + * + * to make the graph unidirectional pass the third parameter of add_edge as + * false which will + */ + adjacency_list[u].push_back(v); // u-->v edge added + if(bidir==true){ + // if graph is bidirectional + adjacency_list[v].push_back(u); // v-->u edge added } } - std::queue q; - q.push(src); - tracker[src]=true; - while(!q.empty()){ - T node = q.front(); - q.pop(); - for(T const &neighbour : adjacency_list[node]){ - if(!tracker[neighbour]){ - q.push(neighbour); - tracker[neighbour]=true; + + + /** + * this function performs the breadth first search on graph and return a + * mapping which maps the nodes to a boolean value representing whether the + * node was traversed or not. + */ + std::map breadth_first_search(T src){ + /// mapping to keep track of all visited nodes + std::map visited; + /// initialise every possible vertex to map to false + /// initially none of the vertices are unvisited + for(auto const &adjlist: adjacency_list){ + visited[adjlist.first]=false; + for(auto const &node:adjacency_list[adjlist.first]){ + visited[node]=false; } } + + /// queue to store the nodes which are yet to be traversed + std::queue tracker; + + /// push the source vertex to queue to begin traversing + tracker.push(src); + ///mark the source vertex as visited + visited[src]=true; + while(!tracker.empty()){ + /// traverse the graph till no connected vertex are left + /// extract a node from queue for further traversal + T node = tracker.front(); + /// remove the node from the queue + tracker.pop(); + for(T const &neighbour : adjacency_list[node]){ + /// check every vertex connected to the node which are still unvisited + if(!visited[neighbour]){ + /// if the neighbour is unvisited , push it into the queue + tracker.push(neighbour); + /// mark the neighbour as visited + visited[neighbour]=true; + } + } + } + return visited; } - return tracker; - } -}; -/* Class definition ends */ + }; + /* Class definition ends */ +} +///Namespace definition over + /** Test function */ static void tests() { /// Test 1 Begin - Graph g; + graph::Graph g; std::map correct_result; g.add_edge(0,1); g.add_edge(1,2); @@ -131,12 +151,12 @@ static void tests() { /// Test 2 Begin returned_result = g.breadth_first_search(0); - + assert(returned_result==correct_result); std::cout << "Test 2 Passed..." << std::endl; /// Test 3 Begins - Graph g2; + graph::Graph g2; g2.add_edge("Gorakhpur","Lucknow",false); g2.add_edge("Gorakhpur","Kanpur",false); @@ -165,7 +185,7 @@ int main() { std::cout << "Enter the number of edges: "; std::cin >> edges; - Graph g; + graph::Graph g; std::cout << "Enter space-separated pairs of vertices that form edges: " << std::endl; From 1cbc00c54181a2017f55b4fe5ddcfe9afe87be70 Mon Sep 17 00:00:00 2001 From: Gpamangkp <41160734+Gpamangkp@users.noreply.github.com> Date: Fri, 23 Oct 2020 09:13:27 +0530 Subject: [PATCH 5/8] Update graph/breadth_first_search.cpp Co-authored-by: David Leal --- graph/breadth_first_search.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/graph/breadth_first_search.cpp b/graph/breadth_first_search.cpp index f7a0a5077..3843ac18a 100644 --- a/graph/breadth_first_search.cpp +++ b/graph/breadth_first_search.cpp @@ -54,7 +54,10 @@ #include #include -///namespace graph which contains the class Graph +/** + * \namespace graph + * \brief Graph algorithms + */ namespace graph{ /* Class Graph definition */ template From 3025fc674c232765094acf631d73953f2634dca6 Mon Sep 17 00:00:00 2001 From: Gpamangkp <41160734+Gpamangkp@users.noreply.github.com> Date: Fri, 23 Oct 2020 09:13:40 +0530 Subject: [PATCH 6/8] Update graph/breadth_first_search.cpp Co-authored-by: David Leal --- graph/breadth_first_search.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graph/breadth_first_search.cpp b/graph/breadth_first_search.cpp index 3843ac18a..1d38fda24 100644 --- a/graph/breadth_first_search.cpp +++ b/graph/breadth_first_search.cpp @@ -4,7 +4,7 @@ * \brief [Breadth First Search Algorithm * (Breadth First Search)](https://en.wikipedia.org/wiki/Breadth-first_search) * - * \author [Ayaan Khan](http://github.com/ayaankhan98) + * \author [Ayaan Khan](https://github.com/ayaankhan98) * \contributor [Aman Kumar Pandey](http://github.com/gpamangkp) * * From c53f29fb53df3c1f3a16ce3c8e7c57be774c65cd Mon Sep 17 00:00:00 2001 From: Gpamangkp <41160734+Gpamangkp@users.noreply.github.com> Date: Fri, 23 Oct 2020 09:13:48 +0530 Subject: [PATCH 7/8] Update graph/breadth_first_search.cpp Co-authored-by: David Leal --- graph/breadth_first_search.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graph/breadth_first_search.cpp b/graph/breadth_first_search.cpp index 1d38fda24..06af41a01 100644 --- a/graph/breadth_first_search.cpp +++ b/graph/breadth_first_search.cpp @@ -5,7 +5,7 @@ * (Breadth First Search)](https://en.wikipedia.org/wiki/Breadth-first_search) * * \author [Ayaan Khan](https://github.com/ayaankhan98) - * \contributor [Aman Kumar Pandey](http://github.com/gpamangkp) + * \author [Aman Kumar Pandey](https://github.com/gpamangkp) * * * \details From f763e8d13773efac82477cd8a1695784655c320e Mon Sep 17 00:00:00 2001 From: Gpamangkp <41160734+Gpamangkp@users.noreply.github.com> Date: Fri, 23 Oct 2020 09:13:58 +0530 Subject: [PATCH 8/8] Update graph/breadth_first_search.cpp Co-authored-by: David Leal --- graph/breadth_first_search.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/graph/breadth_first_search.cpp b/graph/breadth_first_search.cpp index 06af41a01..a0c872681 100644 --- a/graph/breadth_first_search.cpp +++ b/graph/breadth_first_search.cpp @@ -131,7 +131,6 @@ namespace graph{ }; /* Class definition ends */ } -///Namespace definition over /** Test function */