diff --git a/CMakeLists.txt b/CMakeLists.txt index 57104aa9c..f75d558f3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,7 +40,8 @@ add_subdirectory(backtracking) add_subdirectory(data_structures) add_subdirectory(machine_learning) add_subdirectory(numerical_methods) - +add_subdirectory(graph) + cmake_policy(SET CMP0054 NEW) cmake_policy(SET CMP0057 NEW) find_package(Doxygen OPTIONAL_COMPONENTS dot dia) diff --git a/DIRECTORY.md b/DIRECTORY.md index 0349f7039..681b0c3ba 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -71,6 +71,7 @@ * [Tree Height](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/dynamic_programming/tree_height.cpp) ## Geometry + * [Jarvis Algorithm](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/geometry/jarvis_algorithm.cpp) * [Line Segment Intersection](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/geometry/line_segment_intersection.cpp) ## Graph @@ -79,10 +80,11 @@ * [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) * [Cycle Check Directed Graph](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/graph/cycle_check_directed_graph.cpp) - * [Dfs](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/graph/dfs.cpp) - * [Dfs With Stack](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/graph/dfs_with_stack.cpp) + * [Depth First Search](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/graph/depth_first_search.cpp) + * [Depth First Search With Stack](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/graph/depth_first_search_with_stack.cpp) * [Dijkstra](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/graph/dijkstra.cpp) * [Hamiltons Cycle](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/graph/hamiltons_cycle.cpp) + * [Is Graph Bipartite](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/graph/is_graph_bipartite.cpp) * [Kosaraju](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/graph/kosaraju.cpp) * [Kruskal](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/graph/kruskal.cpp) * [Lowest Common Ancestor](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/graph/lowest_common_ancestor.cpp) diff --git a/graph/CMakeLists.txt b/graph/CMakeLists.txt new file mode 100644 index 000000000..02b8f4840 --- /dev/null +++ b/graph/CMakeLists.txt @@ -0,0 +1,20 @@ +# If necessary, use the RELATIVE flag, otherwise each source file may be listed +# with full pathname. RELATIVE may makes it easier to extract an executable name +# automatically. +file( GLOB APP_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.cpp ) +# file( GLOB APP_SOURCES ${CMAKE_SOURCE_DIR}/*.c ) +# AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} APP_SOURCES) +foreach( testsourcefile ${APP_SOURCES} ) + # I used a simple string replace, to cut off .cpp. + string( REPLACE ".cpp" "" testname ${testsourcefile} ) + add_executable( ${testname} ${testsourcefile} ) + + set_target_properties(${testname} PROPERTIES + LINKER_LANGUAGE CXX + ) + if(OpenMP_CXX_FOUND) + target_link_libraries(${testname} OpenMP::OpenMP_CXX) + endif() + install(TARGETS ${testname} DESTINATION "bin/graph") + +endforeach( testsourcefile ${APP_SOURCES} ) diff --git a/graph/cycle_check_directed_graph.cpp b/graph/cycle_check_directed_graph.cpp index a9e4f2c8b..8a651cfc5 100644 --- a/graph/cycle_check_directed_graph.cpp +++ b/graph/cycle_check_directed_graph.cpp @@ -53,7 +53,7 @@ using AdjList = std::map>; */ class Graph { public: - Graph() : m_vertices(0), m_adjList({}) {} + Graph() : m_adjList({}) {} ~Graph() = default; Graph(Graph&&) = default; Graph& operator=(Graph&&) = default; @@ -65,8 +65,8 @@ class Graph { * @param vertices specify the number of vertices the graph would contain. * @param adjList is the adjacency list representation of graph. */ - Graph(unsigned int vertices, AdjList const& adjList) - : m_vertices(vertices), m_adjList(adjList) {} + Graph(unsigned int vertices, AdjList adjList) + : m_vertices(vertices), m_adjList(std::move(adjList)) {} /** Create a graph from vertices and adjacency list. * @@ -142,7 +142,7 @@ class Graph { } private: - unsigned int m_vertices; + unsigned int m_vertices = 0; AdjList m_adjList; }; diff --git a/graph/depth_first_search.cpp b/graph/depth_first_search.cpp new file mode 100644 index 000000000..e99d44fc9 --- /dev/null +++ b/graph/depth_first_search.cpp @@ -0,0 +1,133 @@ +/** + * + * \file + * \brief [Depth First Search Algorithm + * (Depth First Search)](https://en.wikipedia.org/wiki/Depth-first_search) + * + * \author [Ayaan Khan](http://github.com/ayaankhan98) + * + * \details + * Depth First Search also quoted as DFS is a Graph Traversal Algorithm. + * Time Complexity O(|V| + |E|) where V is number of vertices and E + * is number of edges in graph. + * + * Application of Depth First Search are + * + * 1. Finding connected components + * 2. Finding 2-(edge or vertex)-connected components. + * 3. Finding 3-(edge or vertex)-connected components. + * 4. Finding the bridges of a graph. + * 5. Generating words in order to plot the limit set of a group. + * 6. Finding strongly connected components. + * + * And there are many more... + * + *

Working

+ * 1. Mark all vertices as unvisited first + * 2. start exploring from some starting vertex. + * + * While exploring vertex we mark the vertex as visited + * and start exploring the vertices connected to this + * vertex in recursive way. + * + */ + +#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, size_t u, size_t v) { + /* + * + * Here we are considering undirected graph that's the + * reason we are adding v to the adjacency list representation of u + * and also adding u to the adjacency list representation of v + * + */ + (*adj)[u - 1].push_back(v - 1); + (*adj)[v - 1].push_back(u - 1); +} + +/** + * + * \brief + * Explores the given vertex, exploring a vertex means traversing + * over all the vertices which are connected to the vertex that is + * currently being explored. + * + * @param adj garph + * @param v vertex to be explored + * @param visited already visited vertices + * + */ +void explore(const std::vector> &adj, size_t v, + std::vector *visited) { + std::cout << v + 1 << " "; + (*visited)[v] = true; + for (auto x : adj[v]) { + if (!(*visited)[x]) { + explore(adj, x, visited); + } + } +} + +/** + * \brief + * initiates depth first search algorithm. + * + * @param adj adjacency list of graph + * @param start vertex from where DFS starts traversing. + * + */ +void depth_first_search(const std::vector> &adj, + size_t start) { + size_t vertices = adj.size(); + + std::vector visited(vertices, false); + explore(adj, start, &visited); +} +} // namespace graph + +/** Main function */ +int main() { + size_t vertices = 0, edges = 0; + std::cout << "Enter the Vertices : "; + std::cin >> vertices; + std::cout << "Enter the Edges : "; + std::cin >> edges; + + /// creating graph + std::vector> adj(vertices, std::vector()); + + /// taking input for edges + std::cout << "Enter the vertices which have edges between them : " + << std::endl; + while (edges--) { + size_t u = 0, v = 0; + std::cin >> u >> v; + graph::addEdge(&adj, u, v); + } + + /// running depth first search over graph + graph::depth_first_search(adj, 2); + + std::cout << std::endl; + return 0; +} diff --git a/graph/depth_first_search_with_stack.cpp b/graph/depth_first_search_with_stack.cpp new file mode 100644 index 000000000..2d5752322 --- /dev/null +++ b/graph/depth_first_search_with_stack.cpp @@ -0,0 +1,46 @@ +#include +#include +#include +#include + +constexpr int WHITE = 0; +constexpr int GREY = 1; +constexpr int BLACK = 2; +constexpr int INF = 99999; + +void dfs(const std::vector< std::list > &graph, int start) { + std::vector checked(graph.size(), WHITE); + checked[start] = GREY; + std::stack stack; + stack.push(start); + while (!stack.empty()) { + int act = stack.top(); + stack.pop(); + + if (checked[act] == GREY) { + std::cout << act << ' '; + for (auto it : graph[act]) { + stack.push(it); + if (checked[it] != BLACK) { + checked[it] = GREY; + } + } + checked[act] = BLACK; // nodo controllato + } + } +} + +int main() { + int n = 0; + std::cin >> n; + std::vector< std::list > graph(INF); + for (int i = 0; i < n; ++i) { + int u = 0, w = 0; + std::cin >> u >> w; + graph[u].push_back(w); + } + + dfs(graph, 0); + + return 0; +} diff --git a/graph/dfs.cpp b/graph/dfs.cpp deleted file mode 100644 index 2d38c8725..000000000 --- a/graph/dfs.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include -using namespace std; -int v = 4; -void DFSUtil_(int graph[4][4], bool visited[], int s) { - visited[s] = true; - cout << s << " "; - for (int i = 0; i < v; i++) { - if (graph[s][i] == 1 && visited[i] == false) { - DFSUtil_(graph, visited, i); - } - } -} - -void DFS_(int graph[4][4], int s) { - bool visited[v]; - memset(visited, 0, sizeof(visited)); - DFSUtil_(graph, visited, s); -} - -int main() { - int graph[4][4] = {{0, 1, 1, 0}, {0, 0, 1, 0}, {1, 0, 0, 1}, {0, 0, 0, 1}}; - cout << "DFS: "; - DFS_(graph, 2); - cout << endl; - return 0; -} \ No newline at end of file diff --git a/graph/dfs_with_stack.cpp b/graph/dfs_with_stack.cpp deleted file mode 100644 index 193f3f291..000000000 --- a/graph/dfs_with_stack.cpp +++ /dev/null @@ -1,51 +0,0 @@ -#include -#include -#include - -#define WHITE 0 -#define GREY 1 -#define BLACK 2 -#define INF 99999 - -using namespace std; - -int checked[999] = {WHITE}; - -void dfs(const list lista[], int start) { - stack stack; - - int checked[999] = {WHITE}; - - stack.push(start); - - checked[start] = GREY; - while (!stack.empty()) { - int act = stack.top(); - stack.pop(); - - if (checked[act] == GREY) { - cout << act << ' '; - for (auto it = lista[act].begin(); it != lista[act].end(); ++it) { - stack.push(*it); - if (checked[*it] != BLACK) - checked[*it] = GREY; - } - checked[act] = BLACK; // nodo controllato - } - } -} - -int main() { - int u, w; - int n; - cin >> n; - list lista[INF]; - for (int i = 0; i < n; ++i) { - cin >> u >> w; - lista[u].push_back(w); - } - - dfs(lista, 0); - - return 0; -}