From 2b76ab33f33382d454a697f4326cb6129e762e04 Mon Sep 17 00:00:00 2001 From: Marcos Cannabrava Date: Fri, 17 Jul 2020 10:28:46 -0300 Subject: [PATCH 1/3] Fix Non Recursive Depth First Search --- graphs/depth_first_search.py | 54 +++++++++++++++--------------------- 1 file changed, 23 insertions(+), 31 deletions(-) diff --git a/graphs/depth_first_search.py b/graphs/depth_first_search.py index 9ec7083c7fc1..7d1941e3b246 100644 --- a/graphs/depth_first_search.py +++ b/graphs/depth_first_search.py @@ -1,43 +1,35 @@ -"""The DFS function simply calls itself recursively for every unvisited child of -its argument. We can emulate that behaviour precisely using a stack of iterators. -Instead of recursively calling with a node, we'll push an iterator to the node's -children onto the iterator stack. When the iterator at the top of the stack -terminates, we'll pop it off the stack. - -Pseudocode: - all nodes initially unexplored - mark s as explored - for every edge (s, v): - if v unexplored: - DFS(G, v) -""" -from typing import Dict, Set +"""Non recursive implementation of a DFS algorithm.""" + +from typing import Set, Dict def depth_first_search(graph: Dict, start: str) -> Set[int]: """Depth First Search on Graph - :param graph: directed graph in dictionary format - :param vertex: starting vectex as a string - :returns: the trace of the search - >>> G = { "A": ["B", "C", "D"], "B": ["A", "D", "E"], - ... "C": ["A", "F"], "D": ["B", "D"], "E": ["B", "F"], - ... "F": ["C", "E", "G"], "G": ["F"] } - >>> start = "A" - >>> output_G = list({'A', 'B', 'C', 'D', 'E', 'F', 'G'}) - >>> all(x in output_G for x in list(depth_first_search(G, "A"))) - True - >>> all(x in output_G for x in list(depth_first_search(G, "G"))) - True + :param graph: directed graph in dictionary format + :param vertex: starting vertex as a string + :returns: the trace of the search + >>> G = { "A": ["B", "C", "D"], "B": ["A", "D", "E"], + ... "C": ["A", "F"], "D": ["B", "D"], "E": ["B", "F"], + ... "F": ["C", "E", "G"], "G": ["F"] } + >>> start = "A" + >>> output_G = list({'A', 'B', 'C', 'D', 'E', 'F', 'G'}) + >>> all(x in output_G for x in list(depth_first_search(G, "A"))) + True + >>> all(x in output_G for x in list(depth_first_search(G, "G"))) + True """ explored, stack = set(start), [start] + while stack: v = stack.pop() - # one difference from BFS is to pop last element here instead of first one - for w in graph[v]: - if w not in explored: - explored.add(w) - stack.append(w) + explored.add(v) + # Differences from BFS: + # 1) pop last element instead of first one + # 2) add adjacent elements to stack without exploring them + for adj in reversed(graph[v]): + if adj not in explored: + stack.append(adj) return explored From 4529d37efdfaa1c6c7e6cc0d2590ccd249896670 Mon Sep 17 00:00:00 2001 From: Marcos Cannabrava <54267712+marcoscannabrava@users.noreply.github.com> Date: Fri, 11 Sep 2020 10:32:07 -0300 Subject: [PATCH 2/3] Unindent docstring --- graphs/depth_first_search.py | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/graphs/depth_first_search.py b/graphs/depth_first_search.py index 7d1941e3b246..c7bc97806fc5 100644 --- a/graphs/depth_first_search.py +++ b/graphs/depth_first_search.py @@ -5,19 +5,18 @@ def depth_first_search(graph: Dict, start: str) -> Set[int]: """Depth First Search on Graph - - :param graph: directed graph in dictionary format - :param vertex: starting vertex as a string - :returns: the trace of the search - >>> G = { "A": ["B", "C", "D"], "B": ["A", "D", "E"], - ... "C": ["A", "F"], "D": ["B", "D"], "E": ["B", "F"], - ... "F": ["C", "E", "G"], "G": ["F"] } - >>> start = "A" - >>> output_G = list({'A', 'B', 'C', 'D', 'E', 'F', 'G'}) - >>> all(x in output_G for x in list(depth_first_search(G, "A"))) - True - >>> all(x in output_G for x in list(depth_first_search(G, "G"))) - True + :param graph: directed graph in dictionary format + :param vertex: starting vertex as a string + :returns: the trace of the search + >>> G = { "A": ["B", "C", "D"], "B": ["A", "D", "E"], + ... "C": ["A", "F"], "D": ["B", "D"], "E": ["B", "F"], + ... "F": ["C", "E", "G"], "G": ["F"] } + >>> start = "A" + >>> output_G = list({'A', 'B', 'C', 'D', 'E', 'F', 'G'}) + >>> all(x in output_G for x in list(depth_first_search(G, "A"))) + True + >>> all(x in output_G for x in list(depth_first_search(G, "G"))) + True """ explored, stack = set(start), [start] From 0747409cc3e19932b6413253d6578215118a4f6b Mon Sep 17 00:00:00 2001 From: Marcos Cannabrava <54267712+marcoscannabrava@users.noreply.github.com> Date: Fri, 11 Sep 2020 10:59:15 -0300 Subject: [PATCH 3/3] Reindent docstring by 1 space Co-authored-by: Christian Clauss --- graphs/depth_first_search.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/graphs/depth_first_search.py b/graphs/depth_first_search.py index c7bc97806fc5..fee9ea07728d 100644 --- a/graphs/depth_first_search.py +++ b/graphs/depth_first_search.py @@ -5,18 +5,18 @@ def depth_first_search(graph: Dict, start: str) -> Set[int]: """Depth First Search on Graph - :param graph: directed graph in dictionary format - :param vertex: starting vertex as a string - :returns: the trace of the search - >>> G = { "A": ["B", "C", "D"], "B": ["A", "D", "E"], - ... "C": ["A", "F"], "D": ["B", "D"], "E": ["B", "F"], - ... "F": ["C", "E", "G"], "G": ["F"] } - >>> start = "A" - >>> output_G = list({'A', 'B', 'C', 'D', 'E', 'F', 'G'}) - >>> all(x in output_G for x in list(depth_first_search(G, "A"))) - True - >>> all(x in output_G for x in list(depth_first_search(G, "G"))) - True + :param graph: directed graph in dictionary format + :param vertex: starting vertex as a string + :returns: the trace of the search + >>> G = { "A": ["B", "C", "D"], "B": ["A", "D", "E"], + ... "C": ["A", "F"], "D": ["B", "D"], "E": ["B", "F"], + ... "F": ["C", "E", "G"], "G": ["F"] } + >>> start = "A" + >>> output_G = list({'A', 'B', 'C', 'D', 'E', 'F', 'G'}) + >>> all(x in output_G for x in list(depth_first_search(G, "A"))) + True + >>> all(x in output_G for x in list(depth_first_search(G, "G"))) + True """ explored, stack = set(start), [start]