-
Notifications
You must be signed in to change notification settings - Fork 0
/
depth_first_search.py
122 lines (98 loc) · 2.85 KB
/
depth_first_search.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
from collections import defaultdict, deque
from typing import Tuple
def dfs_connectivity_recur(adj_dict: dict[int, list[int]], source: int, destination: int, visited: set = None):
if source == destination:
return True
if visited is None:
visited = set()
visited.add(source)
for adj_node in adj_dict[source]:
if adj_node in visited:
continue
if dfs_connectivity_recur(adj_dict, adj_node, destination, visited):
return True
def dfs_connectivity(adj_dict: dict[int, list[int]], source: int, destination: int):
stack = [source]
visited = {source}
while stack:
current_node = stack.pop()
for adj_node in adj_dict[current_node]:
if adj_node == destination:
return True
if adj_node in visited:
continue
visited.add(adj_node)
stack.append(adj_node)
return False
def dfs_shortest_path_recur(
adj_dict: dict[int, list[int]],
source: int,
destination: int,
visited: set = None,
path: list[int] = None):
if visited is None:
visited = set()
visited.add(source)
if source == destination:
return path
for adj_node in adj_dict[source]:
if adj_node in visited:
continue
result = dfs_shortest_path_recur(adj_dict, adj_node, destination, visited)
if result is not None:
print(source, result)
return [source] + result
def dfs_shortest_path(adj_dict: dict[int, list[int]], source: int, destination: int):
# Init variables
prev = {source: None}
visited = {source}
visit_queue = deque([source])
# Start deque node and iterate
while visit_queue:
current_node = visit_queue.pop()
adj_nodes = adj_dict[current_node]
# Visit nodes
for adj_node in adj_nodes:
if adj_node in visited:
continue
prev[adj_node] = current_node
if adj_node == destination:
break
visit_queue.append(adj_node)
visited.add(adj_node)
if adj_node == destination:
break
# Backtrack path
search_node = prev[destination]
path = [destination]
while True:
if search_node == None:
return None
path.append(search_node)
if search_node == source:
break
search_node = prev[search_node]
path.reverse()
return path
edges = [
(0, 1),
(1, 2),
(2, 3),
(0, 3),
(0, 11),
(11, 12),
(12, 13),
(3, 4),
(3, 5),
(4, 7),
(7, 8),
(7, 9),
(5, 10)
]
# Create two-way connection dict
adj_dict = defaultdict(list)
for start, stop in edges:
adj_dict[start].append(stop)
adj_dict[stop].append(start)
path = dfs_shortest_path_recur(adj_dict, 0 ,13)
print(path)