mirror of
https://github.com/TheAlgorithms/Python.git
synced 2025-01-19 00:37:02 +00:00
Initialize set with source in DFS (#1872)
* Update dfs.py * Add type hints, rearrange doc-strings and comments * fixup! Format Python code with psf/black push * dfs -> depth_first_search Co-Authored-By: Christian Clauss <cclauss@me.com> * dfs -> depth_first_search * Add doctest for DFS * fixup! Format Python code with psf/black push * Rename dfs.py to depth_first_search_dictionary.py * updating DIRECTORY.md * Rename depth_first_search_dictionary.py to depth_first_search_dfs.py * updating DIRECTORY.md * Rename depth_first_search.py to depth_first_search_2.py * updating DIRECTORY.md * Rename depth_first_search_dfs.py to depth_first_search.py * updating DIRECTORY.md Co-authored-by: John Law <johnlaw.po@gmail.com> Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: Christian Clauss <cclauss@me.com>
This commit is contained in:
parent
1c9d4a3929
commit
7aaf79cc23
|
@ -212,7 +212,7 @@
|
||||||
* [Check Bipartite Graph Bfs](https://github.com/TheAlgorithms/Python/blob/master/graphs/check_bipartite_graph_bfs.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)
|
* [Check Bipartite Graph Dfs](https://github.com/TheAlgorithms/Python/blob/master/graphs/check_bipartite_graph_dfs.py)
|
||||||
* [Depth First Search](https://github.com/TheAlgorithms/Python/blob/master/graphs/depth_first_search.py)
|
* [Depth First Search](https://github.com/TheAlgorithms/Python/blob/master/graphs/depth_first_search.py)
|
||||||
* [Dfs](https://github.com/TheAlgorithms/Python/blob/master/graphs/dfs.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)
|
* [Dijkstra](https://github.com/TheAlgorithms/Python/blob/master/graphs/dijkstra.py)
|
||||||
* [Dijkstra 2](https://github.com/TheAlgorithms/Python/blob/master/graphs/dijkstra_2.py)
|
* [Dijkstra 2](https://github.com/TheAlgorithms/Python/blob/master/graphs/dijkstra_2.py)
|
||||||
* [Dijkstra Algorithm](https://github.com/TheAlgorithms/Python/blob/master/graphs/dijkstra_algorithm.py)
|
* [Dijkstra Algorithm](https://github.com/TheAlgorithms/Python/blob/master/graphs/dijkstra_algorithm.py)
|
||||||
|
|
|
@ -1,65 +1,59 @@
|
||||||
#!/usr/bin/python
|
"""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.
|
||||||
|
|
||||||
""" Author: OMKAR PATHAK """
|
Pseudocode:
|
||||||
|
all nodes initially unexplored
|
||||||
|
mark s as explored
|
||||||
|
for every edge (s, v):
|
||||||
|
if v unexplored:
|
||||||
|
DFS(G, v)
|
||||||
|
"""
|
||||||
|
|
||||||
|
from typing import Set, Dict
|
||||||
|
|
||||||
|
|
||||||
class Graph:
|
def depth_first_search(graph: Dict, start: str) -> Set[int]:
|
||||||
def __init__(self):
|
"""Depth First Search on Graph
|
||||||
self.vertex = {}
|
|
||||||
|
|
||||||
# for printing the Graph vertices
|
:param graph: directed graph in dictionary format
|
||||||
def printGraph(self):
|
:param vertex: starting vectex as a string
|
||||||
print(self.vertex)
|
:returns: the trace of the search
|
||||||
for i in self.vertex.keys():
|
>>> G = { "A": ["B", "C", "D"], "B": ["A", "D", "E"],
|
||||||
print(i, " -> ", " -> ".join([str(j) for j in self.vertex[i]]))
|
... "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)
|
||||||
|
return explored
|
||||||
|
|
||||||
# for adding the edge between two vertices
|
|
||||||
def addEdge(self, fromVertex, toVertex):
|
|
||||||
# check if vertex is already present,
|
|
||||||
if fromVertex in self.vertex.keys():
|
|
||||||
self.vertex[fromVertex].append(toVertex)
|
|
||||||
else:
|
|
||||||
# else make a new vertex
|
|
||||||
self.vertex[fromVertex] = [toVertex]
|
|
||||||
|
|
||||||
def DFS(self):
|
|
||||||
# visited array for storing already visited nodes
|
|
||||||
visited = [False] * len(self.vertex)
|
|
||||||
|
|
||||||
# call the recursive helper function
|
|
||||||
for i in range(len(self.vertex)):
|
|
||||||
if visited[i] == False:
|
|
||||||
self.DFSRec(i, visited)
|
|
||||||
|
|
||||||
def DFSRec(self, startVertex, visited):
|
|
||||||
# mark start vertex as visited
|
|
||||||
visited[startVertex] = True
|
|
||||||
|
|
||||||
print(startVertex, end=" ")
|
|
||||||
|
|
||||||
# Recur for all the vertices that are adjacent to this node
|
|
||||||
for i in self.vertex.keys():
|
|
||||||
if visited[i] == False:
|
|
||||||
self.DFSRec(i, visited)
|
|
||||||
|
|
||||||
|
G = {
|
||||||
|
"A": ["B", "C", "D"],
|
||||||
|
"B": ["A", "D", "E"],
|
||||||
|
"C": ["A", "F"],
|
||||||
|
"D": ["B", "D"],
|
||||||
|
"E": ["B", "F"],
|
||||||
|
"F": ["C", "E", "G"],
|
||||||
|
"G": ["F"],
|
||||||
|
}
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
g = Graph()
|
import doctest
|
||||||
g.addEdge(0, 1)
|
|
||||||
g.addEdge(0, 2)
|
|
||||||
g.addEdge(1, 2)
|
|
||||||
g.addEdge(2, 0)
|
|
||||||
g.addEdge(2, 3)
|
|
||||||
g.addEdge(3, 3)
|
|
||||||
|
|
||||||
g.printGraph()
|
doctest.testmod()
|
||||||
print("DFS:")
|
print(depth_first_search(G, "A"))
|
||||||
g.DFS()
|
|
||||||
|
|
||||||
# OUTPUT:
|
|
||||||
# 0 -> 1 -> 2
|
|
||||||
# 1 -> 2
|
|
||||||
# 2 -> 0 -> 3
|
|
||||||
# 3 -> 3
|
|
||||||
# DFS:
|
|
||||||
# 0 1 2 3
|
|
||||||
|
|
65
graphs/depth_first_search_2.py
Normal file
65
graphs/depth_first_search_2.py
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
#!/usr/bin/python
|
||||||
|
|
||||||
|
""" Author: OMKAR PATHAK """
|
||||||
|
|
||||||
|
|
||||||
|
class Graph:
|
||||||
|
def __init__(self):
|
||||||
|
self.vertex = {}
|
||||||
|
|
||||||
|
# for printing the Graph vertices
|
||||||
|
def printGraph(self):
|
||||||
|
print(self.vertex)
|
||||||
|
for i in self.vertex.keys():
|
||||||
|
print(i, " -> ", " -> ".join([str(j) for j in self.vertex[i]]))
|
||||||
|
|
||||||
|
# for adding the edge between two vertices
|
||||||
|
def addEdge(self, fromVertex, toVertex):
|
||||||
|
# check if vertex is already present,
|
||||||
|
if fromVertex in self.vertex.keys():
|
||||||
|
self.vertex[fromVertex].append(toVertex)
|
||||||
|
else:
|
||||||
|
# else make a new vertex
|
||||||
|
self.vertex[fromVertex] = [toVertex]
|
||||||
|
|
||||||
|
def DFS(self):
|
||||||
|
# visited array for storing already visited nodes
|
||||||
|
visited = [False] * len(self.vertex)
|
||||||
|
|
||||||
|
# call the recursive helper function
|
||||||
|
for i in range(len(self.vertex)):
|
||||||
|
if visited[i] == False:
|
||||||
|
self.DFSRec(i, visited)
|
||||||
|
|
||||||
|
def DFSRec(self, startVertex, visited):
|
||||||
|
# mark start vertex as visited
|
||||||
|
visited[startVertex] = True
|
||||||
|
|
||||||
|
print(startVertex, end=" ")
|
||||||
|
|
||||||
|
# Recur for all the vertices that are adjacent to this node
|
||||||
|
for i in self.vertex.keys():
|
||||||
|
if visited[i] == False:
|
||||||
|
self.DFSRec(i, visited)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
g = Graph()
|
||||||
|
g.addEdge(0, 1)
|
||||||
|
g.addEdge(0, 2)
|
||||||
|
g.addEdge(1, 2)
|
||||||
|
g.addEdge(2, 0)
|
||||||
|
g.addEdge(2, 3)
|
||||||
|
g.addEdge(3, 3)
|
||||||
|
|
||||||
|
g.printGraph()
|
||||||
|
print("DFS:")
|
||||||
|
g.DFS()
|
||||||
|
|
||||||
|
# OUTPUT:
|
||||||
|
# 0 -> 1 -> 2
|
||||||
|
# 1 -> 2
|
||||||
|
# 2 -> 0 -> 3
|
||||||
|
# 3 -> 3
|
||||||
|
# DFS:
|
||||||
|
# 0 1 2 3
|
|
@ -1,44 +0,0 @@
|
||||||
"""pseudo-code"""
|
|
||||||
|
|
||||||
"""
|
|
||||||
DFS(graph G, start vertex s):
|
|
||||||
// all nodes initially unexplored
|
|
||||||
mark s as explored
|
|
||||||
for every edge (s, v):
|
|
||||||
if v unexplored:
|
|
||||||
DFS(G, v)
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def dfs(graph, start):
|
|
||||||
"""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."""
|
|
||||||
explored, stack = set(), [start]
|
|
||||||
while stack:
|
|
||||||
v = (
|
|
||||||
stack.pop()
|
|
||||||
) # one difference from BFS is to pop last element here instead of first one
|
|
||||||
|
|
||||||
if v in explored:
|
|
||||||
continue
|
|
||||||
|
|
||||||
explored.add(v)
|
|
||||||
|
|
||||||
for w in graph[v]:
|
|
||||||
if w not in explored:
|
|
||||||
stack.append(w)
|
|
||||||
return explored
|
|
||||||
|
|
||||||
|
|
||||||
G = {
|
|
||||||
"A": ["B", "C"],
|
|
||||||
"B": ["A", "D", "E"],
|
|
||||||
"C": ["A", "F"],
|
|
||||||
"D": ["B"],
|
|
||||||
"E": ["B", "F"],
|
|
||||||
"F": ["C", "E"],
|
|
||||||
}
|
|
||||||
|
|
||||||
print(dfs(G, "A"))
|
|
Loading…
Reference in New Issue
Block a user