diff --git a/BFS.cpp b/BFS.cpp deleted file mode 100644 index 42c7386..0000000 --- a/BFS.cpp +++ /dev/null @@ -1,48 +0,0 @@ -// Author: Aakash Prabhu -#include -#include -#include -using namespace std; - -// BFS Traversal of an undirected and unweighted graph. -void createAndAddEdge(vector adjList[], int u, int v){ - adjList[u].push_back(v); - adjList[v].push_back(u); // do this because undirected graph -} // createAndAddEdge(vector List[], int u, int v) - -void BFS(vector adjList[], vector visitedVertex, int source){ - queue Q; //set up Queue for BFS - int v; - Q.push(source); - while (!Q.empty()){ - v = Q.front(); - visitedVertex.at(v) = true; - Q.pop(); - cout << v << " "; // Print Vertex - for (vector::iterator it = adjList[v].begin(); it != adjList[v].end(); it++) // Visit all children - if (!visitedVertex.at(*it)){ - Q.push(*it); // Push unvisted vertex onto the queue - visitedVertex.at(*it) = true; - } // if not visited - } // While Queue is not empty - cout << endl; -} // BFS - -int main (void){ - // Idea is to implement the adjacency list as an array of vectors: - const int numVertices = 6; // 6 vertices (0,1,2,3,4,5) - int source = 0; - vector adjList[numVertices]; // Create an array of vectors - vector visitedVertex(numVertices, false); - createAndAddEdge(adjList, 0, 1); - createAndAddEdge(adjList, 0, 2); - createAndAddEdge(adjList, 1, 5); - createAndAddEdge(adjList, 2, 3); - createAndAddEdge(adjList, 2, 4); - createAndAddEdge(adjList, 3, 3); - createAndAddEdge(adjList, 4, 4); - createAndAddEdge(adjList, 5, 5); - BFS(adjList, visitedVertex, source); // Perform BFS given graph G and a source s - //Should Print: 0 1 2 5 3 4 - -} // main() diff --git a/DijkstrasAlgorithm.cpp b/DijkstrasAlgorithm.cpp deleted file mode 100644 index 0d92212..0000000 --- a/DijkstrasAlgorithm.cpp +++ /dev/null @@ -1,74 +0,0 @@ -// Author: Aakash Prabhu -#include -#include -#include // To set up priority queue -#include // To use std::greater -> This will prove to be useful in picking the minimum weight -using namespace std; - -/* Uses Dijkstra's Algorithm to find the Shortest Path from an arbitrary vertex to all other vertices - * Since the following version of Dijkstra's is implemented using a min-priority queue, - * the time complexity of the algorithm is O(V + ElogV). - */ - -typedef pair Pair; // First = Weight & Second = Vertex -const int numVertices = 6; // 6 vertices (0,1,2,3,4,5) -vector visitedVertex(numVertices, false); -int ShortestPath[numVertices]; // Have an array to store the shortest path - -void createAndAddEdge(vector adjList[], int u, int weight, int v){ - adjList[u].push_back(make_pair(weight, v)); -} // createAndAddEdge(vector List[], int u, int v, int weight) - -void DijkstrasAlgorithm(vector adjList[], int source){ - priority_queue, greater > PQ; // Set up priority queue - Pair info; - int weight; - ShortestPath[source] = 0; // Set source distance to zero - - for (int i = 0; i < numVertices; i++) - if (i != source) - ShortestPath[i] = 100000; // Initialize everything else to +infinity - - PQ.push(make_pair(0, source)); // Source has weight 0; - - while (!PQ.empty()){ - info = PQ.top(); // Use to get minimum weight - PQ.pop(); // Pop before checking for cycles - source = info.second; // get the vertex - weight = info.first; // current distance - - if (visitedVertex.at(source)) // Check for cycle - continue; // Already accounted for it, move on - - visitedVertex.at(source) = true; // Else, mark the vertex so that we won't have to visit it again - - for (vector::iterator it = adjList[source].begin(); it != adjList[source].end(); it++) - if ((weight + (it->first)) < ShortestPath[it->second]){ // Check if we can do better - ShortestPath[it->second] = weight + (it->first); // Update new distance - PQ.push(make_pair(ShortestPath[it->second], it->second)); // Push vertex and weight onto Priority Queue - } // Update distance - } // While Priority Queue is not empty -} // DijkstrasAlgorithm - -// Driver function -int main (void){ - - int source = 0; - vector adjList[numVertices]; // Create an array of vectors that contain pairs of adjacent vertex and weight - createAndAddEdge(adjList, 0, 5, 1); - createAndAddEdge(adjList, 0, 10, 3); - createAndAddEdge(adjList, 1, 2, 2); - createAndAddEdge(adjList, 1, 10, 5); - createAndAddEdge(adjList, 1, 5, 4); - createAndAddEdge(adjList, 2, 1, 3); - createAndAddEdge(adjList, 2, 5, 4); - createAndAddEdge(adjList, 2, 3, 0); - createAndAddEdge(adjList, 4, 2, 5); - DijkstrasAlgorithm(adjList, source); - - cout << "Shortest path from source vertex " << source << ": "; - for (int i = 0; i < numVertices; i++) - cout << ShortestPath[i] << " "; - cout << endl; - -} // main() diff --git a/IterativeDFS.cpp b/IterativeDFS.cpp deleted file mode 100644 index a6a6873..0000000 --- a/IterativeDFS.cpp +++ /dev/null @@ -1,47 +0,0 @@ -// Author: Aakash Prabhu -#include -#include -#include -using namespace std; - -// DFS Traversal of an undirected and unweighted graph. -void createAndAddEdge(vector adjList[], int u, int v){ - adjList[u].push_back(v); - adjList[v].push_back(u); // do this because undirected graph -} // createAndAddEdge(vector List[], int u, int v) - -void DFS(vector adjList[], vector visitedVertex, int source){ - stack S; //set up Queue for BFS - int v; - S.push(source); - while (!S.empty()){ - v = S.top(); - visitedVertex.at(v) = true; - S.pop(); - cout << v << " "; // Print Vertex - for (vector::iterator it = adjList[v].begin(); it != adjList[v].end(); it++) // Go as far as we can go and then backtrack - if (!visitedVertex.at(*it)){ - S.push(*it); // Push unvisted vertex onto the stack - visitedVertex.at(*it) = true; - } // if not visited - } // While Stack is not empty - cout << endl; -} // DFS - -int main (void){ - // Idea is to implement the adjacency list as an array of vectors: - const int numVertices = 5; // 6 vertices (0,1,2,3,4,5) - int source = 0; - vector adjList[numVertices]; // Create an array of vectors - vector visitedVertex(numVertices, false); - createAndAddEdge(adjList, 0, 1); - createAndAddEdge(adjList, 0, 2); - createAndAddEdge(adjList, 1, 3); - createAndAddEdge(adjList, 1, 4); - createAndAddEdge(adjList, 3, 3); - createAndAddEdge(adjList, 4, 4); - createAndAddEdge(adjList, 2, 2); - DFS(adjList, visitedVertex, source); // Perform DFS given graph G and a source s - //Should Print: 0 2 1 4 3 - -} // main() diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..4406c81 --- /dev/null +++ b/Makefile @@ -0,0 +1,19 @@ +CC := g++ +CC_FLAGS := -Wall -Werror -std=c++11 + +targets = bfs dfs + +all: $(targets) + +bfs: bfs.cc + $(CC) $(CC_FLAGS) $< -o $@ + +dfs: dfs.cc + $(CC) $(CC_FLAGS) $< -o $@ + +clean: + rm -f $(targets) + +remake: + make clean \ + && make diff --git a/PrimsAlgorithm.cpp b/PrimsAlgorithm.cpp deleted file mode 100644 index 1581a0f..0000000 --- a/PrimsAlgorithm.cpp +++ /dev/null @@ -1,54 +0,0 @@ -// Author: Aakash Prabhu -#include -#include -#include // To set up priority queue -#include // To use std::greater -> This will prove to be useful in picking the minimum weight -using namespace std; - -/* Program that uses Prims Algorithm to generate a Minimum Spanning Tree - * and hence find the minimum cost to connect all the vertices - */ - -typedef pair Pair; // First = Weight & Second = Vertex -const int numVertices = 4; // 4 vertices (0,1,2,3) -vector visitedVertex(numVertices, false); - -void createAndAddEdge(vector adjList[], int u, int weight, int v){ - adjList[u].push_back(make_pair(weight, v)); - adjList[v].push_back(make_pair(weight, u)); // do this because undirected graph -} // createAndAddEdge(vector List[], int u, int v, int weight) - -void PrimsAlgorithm(vector adjList[], int source){ - priority_queue, greater > PQ; // Set up priority queue - Pair info; - int minCost = 0; - PQ.push(make_pair(0, source)); // Source has weight 0; - while (!PQ.empty()){ - info = PQ.top(); // Use to get minimum weight - source = info.second; // get the vertex - PQ.pop(); // Pop before checking for cycles - if (visitedVertex.at(source)) // Check for cycle - continue; // Already accounted for it, move on - visitedVertex.at(source) = true; // Else, mark the vertex so that we won't have to visit it again - cout << "Mark vertex " << info.second << " and add weight " << info.first << endl; - minCost += info.first; // Add to minCost - for (vector::iterator it = adjList[source].begin(); it != adjList[source].end(); it++) // Visit all children - if (!visitedVertex.at(it->second)) // If vertex hasn't been visited already - PQ.push(make_pair(it->first, it->second)); // Push vertex and weight onto Priority Queue - } // While Priority Queue is not empty - cout << "Minimum cost to connect all vertices : " << minCost << endl; -} // PrimsAlgorithm - -int main (void){ - // Idea is to implement the adjacency list as an array of vectors: - int source = 0; - vector adjList[numVertices]; // Create an array of vectors that contain pairs of adjacent vertex and weight - createAndAddEdge(adjList, 0, 1, 1); - createAndAddEdge(adjList, 0, 2, 3); - createAndAddEdge(adjList, 1, 4, 2); - createAndAddEdge(adjList, 1, 3, 3); - createAndAddEdge(adjList, 2, 5, 3); - PrimsAlgorithm(adjList, source); // Generate MST and find minCost - // Minimum Cost should be 7; - -} // main() diff --git a/RecursiveDFS.cpp b/RecursiveDFS.cpp deleted file mode 100644 index c33fbb9..0000000 --- a/RecursiveDFS.cpp +++ /dev/null @@ -1,37 +0,0 @@ -// Author: Aakash Prabhu -#include -#include -using namespace std; - -// Recursive DFS Traversal of an undirected and unweighted graph. -void createAndAddEdge(vector adjList[], int u, int v){ - adjList[u].push_back(v); - adjList[v].push_back(u); // do this because undirected graph -} // createAndAddEdge(vector List[], int u, int v) - -void RecursiveDFS(vector adjList[], vector visitedVertex, int source){ - visitedVertex.at(source) = true; - cout << source << " "; // Print Vertex - for (vector::iterator it = adjList[source].begin(); it != adjList[source].end(); it++) - if (!visitedVertex[*it]) - RecursiveDFS(adjList, visitedVertex, *it); // Go as far as possible by recursing. -} // DFS - -int main (void){ - // Idea is to implement the adjacency list as an array of vectors: - const int numVertices = 5; // 6 vertices (0,1,2,3,4,5) - int source = 0; - vector adjList[numVertices]; // Create an array of vectors - vector visitedVertex(numVertices, false); // have a visted vector initialized to false - createAndAddEdge(adjList, 0, 1); - createAndAddEdge(adjList, 0, 2); - createAndAddEdge(adjList, 1, 3); - createAndAddEdge(adjList, 1, 4); - createAndAddEdge(adjList, 3, 3); // Do this because no children! - createAndAddEdge(adjList, 4, 4); - createAndAddEdge(adjList, 2, 2); - RecursiveDFS(adjList, visitedVertex, source); // Perform DFS given graph G and a source s - cout << endl; - //Should Print: 0 1 3 4 2 - -} // main() diff --git a/ShortestPathBFS.cpp b/ShortestPathBFS.cpp deleted file mode 100644 index c6c2667..0000000 --- a/ShortestPathBFS.cpp +++ /dev/null @@ -1,62 +0,0 @@ -// Author: Aakash Prabhu -#include -#include -#include -using namespace std; - -/* Find the shortest path for an unweighted, undirected graph - * We will use BFS to traverse the graph. - * Shortest Path using only BFS will work if there are no cycles and if the graph is unweighted or if all edges have same weight - */ - -void createAndAddEdge(vector adjList[], int u, int v){ - adjList[u].push_back(v); - adjList[v].push_back(u); // do this because undirected graph -} // createAndAddEdge(vector List[], int u, int v) - -void ShortestPath(vector adjList[], vector visitedVertex, int source){ - int v; - queue Q; //set up Queue for BFS - vector ShortestPaths(visitedVertex.size()); - ShortestPaths.at(source) = 0; - for (int i = 0; i < ShortestPaths.size(); i++) - if (i != source) - ShortestPaths.at(i) = 1000000; // All other distances have been set to +infinity - Q.push(source); - - while (!Q.empty()){ - v = Q.front(); - visitedVertex.at(v) = true; - Q.pop(); - for (vector::iterator it = adjList[v].begin(); it != adjList[v].end(); it++) // Visit all children - if (!visitedVertex.at(*it)){ - Q.push(*it); // Push unvisted vertex onto the queue - - if (ShortestPaths.at(v) + 1 < ShortestPaths.at(*it)) - ShortestPaths.at(*it) = ShortestPaths.at(v) + 1; // Get new distance - visitedVertex.at(*it) = true; - } // if not visited - } // While Queue is not empty - cout << "Shortest paths from " << source << ": "; - for (int i = 0; i < ShortestPaths.size(); i++) - cout << ShortestPaths.at(i) << " "; - cout << endl; -} // ShortestPath - -// Driver function -int main (void){ - const int numVertices = 6; // 6 vertices (0,1,2,3,4,5) - int source = 0; - vector adjList[numVertices]; // Create an array of vectors - vector visitedVertex(numVertices, false); - createAndAddEdge(adjList, 0, 1); - createAndAddEdge(adjList, 1, 2); - createAndAddEdge(adjList, 1, 5); - createAndAddEdge(adjList, 2, 3); - createAndAddEdge(adjList, 2, 4); - createAndAddEdge(adjList, 3, 3); - createAndAddEdge(adjList, 4, 4); - createAndAddEdge(adjList, 5, 5); - ShortestPath(adjList, visitedVertex, source); // Find the shortest path from the source to all other vertices. - //Shortest Path from 0: 0 1 2 3 3 2 -} // main() diff --git a/TopologicalSort.cpp b/TopologicalSort.cpp deleted file mode 100644 index 73e5fdc..0000000 --- a/TopologicalSort.cpp +++ /dev/null @@ -1,77 +0,0 @@ -// Author: Aakash Prabhu -#include -#include -#include -using namespace std; - -/* This program demonstrates the working of Topological Sort. - * Topological Sort only works for a directed acyclic graph. - * I have implemented this algorithm with the help of BFS. - * Therefore, the overall time complexity is simply O(|V| + |E|) - */ - -const int numVertices = 6; // 6 vertices (0,1,2,3,4,5) -int source; -vector visitedVertex(numVertices, false); // Mark everything as unvisited -vector inDegree(numVertices, 0); // Initialize all in-Degrees to 0 -vector T; // This will store the vertices that TopologicalSort visits in order. -void createAndAddEdge(vector adjList[], int u, int v){ - adjList[u].push_back(v); -} // To create adjacency list - -void TopologicalSort(vector adjList[]){ - queue Q; //set up Queue for BFS - int v; - - for (int i = 0; i < numVertices; i++) // for all vertices in the graph - for (vector ::iterator it = adjList[i].begin(); it != adjList[i].end(); it++) // visit it's neighbors - inDegree.at(*it)++; //increment inDegree of that child - - for (int i = 0; i < numVertices; i++) - if (inDegree.at(i) == 0){ - source = i; - Q.push(source); // Push it onto the queue as a starting point for BFS - visitedVertex.at(source) = true; // Mark it true - break; - } // Found a vertex with 0 inDegree -> This will be our source for Topological Sort - - while (!Q.empty()){ - v = Q.front(); // Get v - Q.pop(); - T.push_back(v); // Add to T-Vector - - /* Now to proceed with Topological Sort, we remove the vertex and all its corresponding edges. - * Which means, the in-degree's of all it's neighbors will be reduced by 1 - */ - - for (vector::iterator it = adjList[v].begin(); it != adjList[v].end(); it++) // Visit all neighbors - if (!visitedVertex.at(*it)){ - inDegree.at(*it)--; // Decrement inDegree of the neighbor, because its parent vertex has been removed - if (inDegree.at(*it) == 0){ - Q.push(*it); // Push the vertex with least inDegree -> New Source - visitedVertex.at(*it) = true; // Mark it to be true - } // Find new source - } // if not visited - } // While Queue is not empty -} // TopologicalSort(vector adjList[]) - -int main (void){ - vector adjList[numVertices]; // Create an array of vectors - createAndAddEdge(adjList, 0, 1); - createAndAddEdge(adjList, 0, 3); - createAndAddEdge(adjList, 1, 2); - createAndAddEdge(adjList, 1, 3); - createAndAddEdge(adjList, 2, 3); - createAndAddEdge(adjList, 2, 4); - createAndAddEdge(adjList, 2, 5); - createAndAddEdge(adjList, 3, 4); - createAndAddEdge(adjList, 3, 5); - createAndAddEdge(adjList, 4, 5); - TopologicalSort(adjList); // Topological Sort for a given DAG - cout << "Topological Sort for the given DAG: "; - for (int i = 0; i < T.size(); i++) - cout << T.at(i) << " "; - cout << endl; - //Should Print: 0 1 2 3 4 5 - -} // main() diff --git a/bfs.cc b/bfs.cc new file mode 100644 index 0000000..d07268c --- /dev/null +++ b/bfs.cc @@ -0,0 +1,32 @@ +#include "graph.h" +#include +#include + +void BFS(Graph &G, int source) { + std::queue q; + q.push(source); + G.SetVisited(source); + + while (!q.empty()) { + int v = q.front(); + q.pop(); + std::cout << "Visiting: " << v << std::endl; + + for (auto &u : G.Adj(v)) { + if (!G.IsVisited(u)) { + q.push(u); + G.SetVisited(u); + } + } + } +} + +int main(int argc, char **argv) { + std::ifstream ifs(argv[1]); + int source = std::stoi(argv[2]); + + Graph G(ifs); + BFS(G, source); + + return 1; +} diff --git a/dfs.cc b/dfs.cc new file mode 100644 index 0000000..bf516af --- /dev/null +++ b/dfs.cc @@ -0,0 +1,22 @@ +#include "graph.h" +#include +#include + +void DFS(Graph &G, int source) { + G.SetVisited(source); + std::cout << "Visiting: " << source << std::endl; + + for (auto u : G.Adj(source)) + if (!G.IsVisited(u)) + DFS(G, u); +} + +int main(int argc, char **argv) { + std::ifstream ifs(argv[1]); + int source = std::stoi(argv[2]); + + Graph G(ifs); + DFS(G, source); + + return 1; +} diff --git a/graph.h b/graph.h new file mode 100644 index 0000000..2502402 --- /dev/null +++ b/graph.h @@ -0,0 +1,78 @@ +#ifndef GRAPH_H_ +#define GRAPH_H_ + +#include +#include + +class Graph { +private: + int num_vertices; + int num_edges; + std::vector> adj_list; + std::vector visited; + +public: + // Create an empty graph with @V vertices + Graph(int V); + // Create a graph from a file + Graph(std::ifstream &ifs); + // Add undirected edge between @u and @v + void AddEdge(int u, int v); + // Return the number of vertices; + const int V(); + // Return the number of edges + const int E(); + // Return vertices adjacent to @v + std::vector Adj(const int v); + // Get if @v has been visited + bool IsVisited(int v); + // Set @v as visited + void SetVisited(int v); +}; + +Graph::Graph(int V) { + num_vertices = V; + adj_list.resize(V); + visited.resize(V); +} + +Graph::Graph(std::ifstream &ifs) { + ifs >> num_vertices; + adj_list.resize(num_vertices); + visited.resize(num_vertices); + + int u, v; + while (ifs >> u >> v) + AddEdge(u, v); + + for (int i = 0; i < num_vertices; i++) + visited[i] = false; + +} + +void Graph::AddEdge(int u, int v) { + adj_list[u].push_back(v); + adj_list[v].push_back(u); + num_edges++; +} + +const int Graph::V() { + return num_vertices; +} +const int Graph::E() { + return num_edges; +} + +std::vector Graph::Adj(const int v) { + return adj_list[v]; +} + +bool Graph::IsVisited(int v) { + return visited[v]; +} + +void Graph::SetVisited(int v) { + visited[v] = true; +} + +#endif diff --git a/kruskals.cpp b/kruskals.cpp deleted file mode 100644 index 3ebb1d5..0000000 --- a/kruskals.cpp +++ /dev/null @@ -1,131 +0,0 @@ -// C++ program for Kruskal's algorithm to find Minimum -// Spanning Tree of a given connected, undirected and -// weighted graph -#include -using namespace std; - -// Creating shortcut for an integer pair - - -// Structure to represent a graph -struct Graph -{ - int V, E; - vector< pair> > edges; - Graph(int V, int E) - { - this->V = V; - this->E = E; - } - // Utility function to add an edge - void addEdge(int u, int w, int v) - { - edges.push_back({w, {u, v}}); - } - int kruskalMST(); -}; - -// To represent Disjoint Sets -struct DisjointSets -{ - int *parent, *rnk; - int n; - - // Constructor. - DisjointSets(int n) - { - // Allocate memory - this->n = n; - parent = new int[n+1]; - rnk = new int[n+1]; - for (int i = 0; i <= n; i++) - { - rnk[i] = 0; - parent[i] = i; - } - } - int find(int u) - { - if (u != parent[u]) - parent[u] = find(parent[u]); - return parent[u]; - } - - // Union by rank - void merge(int x, int y) - { - x = find(x), y = find(y); - - /* Make tree with smaller height - a subtree of the other tree */ - if (rnk[x] > rnk[y]) - parent[y] = x; - else // If rnk[x] <= rnk[y] - parent[x] = y; - - if (rnk[x] == rnk[y]) - rnk[y]++; - } -}; - -/* Functions returns weight of the MST*/ - -int Graph::kruskalMST() -{ - int mst_wt = 0; // Initialize result - - // Sort edges in increasing order on basis of cost - sort(edges.begin(), edges.end()); - - // Create disjoint sets - DisjointSets ds(V); - - // Iterate through all sorted edges - vector< pair> >::iterator it; - for (it=edges.begin(); it!=edges.end(); it++) - { - int u = it->second.first; - int v = it->second.second; - - int set_u = ds.find(u); - int set_v = ds.find(v); - - // Check if the selected edge is creating - // a cycle or not (Cycle is created if u - // and v belong to same set) - if (set_u != set_v) - { - cout << u << " - " << v << endl; - mst_wt += it->first; - ds.merge(set_u, set_v); - } - } - - return mst_wt; -} - -// Driver program to test above functions -int main() -{ - /* Let us create above shown weighted - and unidrected graph */ - int V = 9, E = 14; - Graph g(V, E); - // making above shown graph - g.addEdge(0, 5, 1); - g.addEdge(0, 10, 3); - g.addEdge(1, 2, 2); - g.addEdge(1, 10, 5); - g.addEdge(1, 5, 4); - g.addEdge(2, 1, 3); - g.addEdge(2, 5, 4); - g.addEdge(2, 3, 0); - g.addEdge(4, 2, 5); - - cout << "Edges of MST are \n"; - int mst_wt = g.kruskalMST(); - - cout << "\nWeight of MST is " << mst_wt; - - return 0; -} diff --git a/test_graphs/test_simple.txt b/test_graphs/test_simple.txt new file mode 100644 index 0000000..c0bc4d8 --- /dev/null +++ b/test_graphs/test_simple.txt @@ -0,0 +1,7 @@ +5 +0 1 +0 2 +1 3 +2 4 +3 4 +4 4