mirror of
https://github.com/TheAlgorithms/Python.git
synced 2025-01-18 16:27: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 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)
|
||||
* [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 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)
|
||||
|
|
|
@ -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 __init__(self):
|
||||
self.vertex = {}
|
||||
def depth_first_search(graph: Dict, start: str) -> Set[int]:
|
||||
"""Depth First Search on Graph
|
||||
|
||||
# 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]]))
|
||||
: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
|
||||
"""
|
||||
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__":
|
||||
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)
|
||||
import doctest
|
||||
|
||||
g.printGraph()
|
||||
print("DFS:")
|
||||
g.DFS()
|
||||
|
||||
# OUTPUT:
|
||||
# 0 -> 1 -> 2
|
||||
# 1 -> 2
|
||||
# 2 -> 0 -> 3
|
||||
# 3 -> 3
|
||||
# DFS:
|
||||
# 0 1 2 3
|
||||
doctest.testmod()
|
||||
print(depth_first_search(G, "A"))
|
||||
|
|
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