From f5a617cc8bb7f5db812c12a60528300b36073378 Mon Sep 17 00:00:00 2001 From: nikalosa Date: Sun, 14 Jun 2020 14:44:13 +0400 Subject: [PATCH 1/7] Implement connected components algorithm for graphs --- graphs/connected_components.py | 77 ++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 graphs/connected_components.py diff --git a/graphs/connected_components.py b/graphs/connected_components.py new file mode 100644 index 000000000000..a2c7fca57b92 --- /dev/null +++ b/graphs/connected_components.py @@ -0,0 +1,77 @@ +''' +https://en.wikipedia.org/wiki/Component_(graph_theory) + +Finding connected components in graph + +''' + +test_graph_1 = { + 0: [1, 2], + 1: [0, 3], + 2: [0], + 3: [1], + 4: [5, 6], + 5: [4, 6], + 6: [4, 5], +} + +test_graph_2 = { + 0: [1, 2, 3], + 1: [0, 3], + 2: [0], + 3: [0, 1], + 4: [], + 5: [], +} + + +def dfs(graph, vert, visited): + """ + Use depth first search to find all vertexes + being in the same component as initial vertex + """ + + visited[vert] = True + + connected_verts = [] + + # iterate over neighbours and + # call the same function for not-visited vertexes + for neighbour in graph[vert]: + if not visited[neighbour]: + connected_verts += dfs(graph, neighbour, visited) + + return [vert] + connected_verts + + +def connected_components(graph): + """ + This function takes graph as a parameter + and then returns the list of connected components + >>> connected_components(test_graph_1) + [[0, 1, 3, 2], [4, 5, 6]] + >>> connected_components(test_graph_2) + [[0, 1, 3, 2], [4], [5]] + """ + + n = len(graph) + + visited = n * [False] + + components_list = [] + + # for each unused vertexes + # we have to call dfs function + # and get its components + for i in range(n): + if not visited[i]: + i_connected = dfs(graph, i, visited) + # when we get components append them to answer list + components_list.append(i_connected) + + return components_list + + +if __name__ == "__main__": + import doctest + doctest.testmod() From dea50d00fc7afdfae5775c0750e4e62b24fbd69c Mon Sep 17 00:00:00 2001 From: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Date: Sun, 14 Jun 2020 10:45:03 +0000 Subject: [PATCH 2/7] fixup! Format Python code with psf/black push --- graphs/connected_components.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/graphs/connected_components.py b/graphs/connected_components.py index a2c7fca57b92..0a9dc8b1bd32 100644 --- a/graphs/connected_components.py +++ b/graphs/connected_components.py @@ -1,9 +1,9 @@ -''' +""" https://en.wikipedia.org/wiki/Component_(graph_theory) Finding connected components in graph -''' +""" test_graph_1 = { 0: [1, 2], @@ -74,4 +74,5 @@ def connected_components(graph): if __name__ == "__main__": import doctest + doctest.testmod() From a4762b69663b4efd4931f2708c62df3dbed3f76b Mon Sep 17 00:00:00 2001 From: nikalosa Date: Sun, 14 Jun 2020 15:03:30 +0400 Subject: [PATCH 3/7] Add parameters and return values annotations with Python type hints --- graphs/connected_components.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graphs/connected_components.py b/graphs/connected_components.py index a2c7fca57b92..631a3f74b7f4 100644 --- a/graphs/connected_components.py +++ b/graphs/connected_components.py @@ -44,7 +44,7 @@ def dfs(graph, vert, visited): return [vert] + connected_verts -def connected_components(graph): +def connected_components(graph: dict) -> list: """ This function takes graph as a parameter and then returns the list of connected components From 63c36a96a710b2a921970de3fb62eecf5f55181b Mon Sep 17 00:00:00 2001 From: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Date: Sun, 14 Jun 2020 11:05:27 +0000 Subject: [PATCH 4/7] updating DIRECTORY.md --- DIRECTORY.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/DIRECTORY.md b/DIRECTORY.md index c90043aa734f..fce4e4273066 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -231,6 +231,7 @@ * [Breadth First Search Shortest Path](https://github.com/TheAlgorithms/Python/blob/master/graphs/breadth_first_search_shortest_path.py) * [Check Bipartite Graph Bfs](https://github.com/TheAlgorithms/Python/blob/master/graphs/check_bipartite_graph_bfs.py) * [Check Bipartite Graph Dfs](https://github.com/TheAlgorithms/Python/blob/master/graphs/check_bipartite_graph_dfs.py) + * [Connected Components](https://github.com/TheAlgorithms/Python/blob/master/graphs/connected_components.py) * [Depth First Search](https://github.com/TheAlgorithms/Python/blob/master/graphs/depth_first_search.py) * [Depth First Search 2](https://github.com/TheAlgorithms/Python/blob/master/graphs/depth_first_search_2.py) * [Dijkstra](https://github.com/TheAlgorithms/Python/blob/master/graphs/dijkstra.py) @@ -264,6 +265,7 @@ * [Test Knapsack](https://github.com/TheAlgorithms/Python/blob/master/greedy_method/test_knapsack.py) ## Hashes + * [Adler32](https://github.com/TheAlgorithms/Python/blob/master/hashes/adler32.py) * [Chaos Machine](https://github.com/TheAlgorithms/Python/blob/master/hashes/chaos_machine.py) * [Enigma Machine](https://github.com/TheAlgorithms/Python/blob/master/hashes/enigma_machine.py) * [Hamming Code](https://github.com/TheAlgorithms/Python/blob/master/hashes/hamming_code.py) From 817b56de7ed773c4b6688c96ebab922332c365ba Mon Sep 17 00:00:00 2001 From: Nika Losaberidze Date: Mon, 15 Jun 2020 18:48:46 +0400 Subject: [PATCH 5/7] Add doctests and typehints --- graphs/connected_components.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/graphs/connected_components.py b/graphs/connected_components.py index de427014fd2e..5f3741e172a5 100644 --- a/graphs/connected_components.py +++ b/graphs/connected_components.py @@ -25,10 +25,14 @@ } -def dfs(graph, vert, visited): +def dfs(graph: dict, vert: int, visited: list) -> list: """ Use depth first search to find all vertexes being in the same component as initial vertex + >>> dfs(test_graph_1, 0, 5 * [False]) + [0, 1, 3, 2] + >>> dfs(test_graph_2, 0, 6 * [False]) + [0, 1, 3, 2] """ visited[vert] = True From e2023cfd2c19688c2afdca3b83d790e047b65e86 Mon Sep 17 00:00:00 2001 From: Nika Losaberidze Date: Wed, 17 Jun 2020 16:55:45 +0400 Subject: [PATCH 6/7] Remove unnecessary comments, change variable names --- graphs/connected_components.py | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/graphs/connected_components.py b/graphs/connected_components.py index 5f3741e172a5..d2cddf2c6e0e 100644 --- a/graphs/connected_components.py +++ b/graphs/connected_components.py @@ -36,11 +36,8 @@ def dfs(graph: dict, vert: int, visited: list) -> list: """ visited[vert] = True - connected_verts = [] - # iterate over neighbours and - # call the same function for not-visited vertexes for neighbour in graph[vert]: if not visited[neighbour]: connected_verts += dfs(graph, neighbour, visited) @@ -58,19 +55,14 @@ def connected_components(graph: dict) -> list: [[0, 1, 3, 2], [4], [5]] """ - n = len(graph) - - visited = n * [False] - + graph_size = len(graph) + visited = graph_size * [False] components_list = [] - # for each unused vertexes - # we have to call dfs function - # and get its components - for i in range(n): + + for i in range(graph_size): if not visited[i]: i_connected = dfs(graph, i, visited) - # when we get components append them to answer list components_list.append(i_connected) return components_list @@ -78,5 +70,4 @@ def connected_components(graph: dict) -> list: if __name__ == "__main__": import doctest - doctest.testmod() From 5bc21bf2108350b34e65f49410f022e73957a249 Mon Sep 17 00:00:00 2001 From: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Date: Wed, 17 Jun 2020 12:56:25 +0000 Subject: [PATCH 7/7] fixup! Format Python code with psf/black push --- graphs/connected_components.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graphs/connected_components.py b/graphs/connected_components.py index d2cddf2c6e0e..b5ef8c292b29 100644 --- a/graphs/connected_components.py +++ b/graphs/connected_components.py @@ -59,7 +59,6 @@ def connected_components(graph: dict) -> list: visited = graph_size * [False] components_list = [] - for i in range(graph_size): if not visited[i]: i_connected = dfs(graph, i, visited) @@ -70,4 +69,5 @@ def connected_components(graph: dict) -> list: if __name__ == "__main__": import doctest + doctest.testmod()