-
Notifications
You must be signed in to change notification settings - Fork 0
/
traversal.py
65 lines (57 loc) · 1.87 KB
/
traversal.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
"""traversal.py
Chris Fisher, 2023
BFS traversal algorithm for finding the furthest vertex from a
given starting node in order to find the diameter of an unweighted
directed graph.
"""
import queue
from collections import deque
def bfs_traversal(graph: dict, start: int) -> list:
# Have to include this since there are some page IDs which don't link
# to any other pages, so as a result don't show up consistently in the adjacency list
all_vertices = set()
for key in graph:
all_vertices.add(key)
for _ in graph[key]:
all_vertices.add(_)
visited = dict()
prev = dict()
for vertex in all_vertices:
visited[vertex] = False
prev[vertex] = None
q = deque()
q.append(start)
visited[start] = True
while q:
u = q.popleft()
try:
for v in graph[u]:
try:
if not visited[v]:
visited[v] = True
prev[v] = u
q.append(v)
# If there are no vertices left to traverse, return u and the path
if not q:
return get_bfs_path(u, prev)
except IndexError as e:
print(f'v: {v} length of visited: {len(visited)}')
raise e
except KeyError:
# Inelegant way of handling vertices with out_degree of 0
visited[v] = True
prev[v] = u
continue
return [-1] # If there is no path return -1
def get_bfs_path(end: int, prev: dict) -> list:
# Reconstructs shortest path
stack = queue.LifoQueue()
predecessor = prev[end]
stack.put(end)
while predecessor:
stack.put(predecessor)
predecessor = prev[predecessor]
path = []
while not stack.empty():
path.append(stack.get())
return path