Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 25d71ff

Browse files
committed
Add BFS implementation
1 parent 04c28e0 commit 25d71ff

File tree

1 file changed

+112
-0
lines changed

1 file changed

+112
-0
lines changed
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
from queue import Queue
2+
3+
class Graph:
4+
# Constructor
5+
def __init__(self, num_of_nodes, directed=True):
6+
self.m_num_of_nodes = num_of_nodes
7+
self.m_nodes = range(self.m_num_of_nodes)
8+
9+
# Directed or Undirected
10+
self.m_directed = directed
11+
12+
# Graph representation - Adjacency list
13+
# We use a dictionary to implement an adjacency list
14+
self.m_adj_list = {node: set() for node in self.m_nodes}
15+
16+
# Add edge to the graph
17+
def add_edge(self, node1, node2, weight=1):
18+
self.m_adj_list[node1].add((node2, weight))
19+
20+
if not self.m_directed:
21+
self.m_adj_list[node2].add((node1, weight))
22+
23+
# Print the graph representation
24+
def print_adj_list(self):
25+
for key in self.m_adj_list.keys():
26+
print("node", key, ": ", self.m_adj_list[key])
27+
28+
def bfs(self, start_node, target_node):
29+
# Set of visited nodes to prevent loops
30+
visited = set()
31+
queue = Queue()
32+
33+
# Add the start_node to the queue and visited list
34+
queue.put(start_node)
35+
visited.add(start_node)
36+
37+
# start_node has not parents
38+
parent = dict()
39+
parent[start_node] = None
40+
41+
# Perform step 3
42+
path_found = False
43+
while not queue.empty():
44+
current_node = queue.get()
45+
if current_node == target_node:
46+
path_found = True
47+
break
48+
49+
for (next_node, weight) in self.m_adj_list[current_node]:
50+
if next_node not in visited:
51+
queue.put(next_node)
52+
parent[next_node] = current_node
53+
visited.add(next_node)
54+
55+
# Path reconstruction
56+
path = []
57+
if path_found:
58+
path.append(target_node)
59+
while parent[target_node] is not None:
60+
path.append(parent[target_node])
61+
target_node = parent[target_node]
62+
path.reverse()
63+
return path
64+
65+
def bfs_traversal(self, start_node):
66+
visited = set()
67+
queue = Queue()
68+
queue.put(start_node)
69+
visited.add(start_node)
70+
71+
while not queue.empty():
72+
current_node = queue.get()
73+
print(current_node, end = " ")
74+
for (next_node, weight) in self.m_adj_list[current_node]:
75+
if next_node not in visited:
76+
queue.put(next_node)
77+
visited.add(next_node)
78+
79+
def main():
80+
# Testing the `bfs()` method
81+
graph1 = Graph(6, directed=False)
82+
83+
graph1.add_edge(0, 1)
84+
graph1.add_edge(0, 2)
85+
graph1.add_edge(0, 3)
86+
graph1.add_edge(0, 4)
87+
graph1.add_edge(1, 2)
88+
graph1.add_edge(2, 3)
89+
graph1.add_edge(2, 5)
90+
graph1.add_edge(3, 4)
91+
graph1.add_edge(3, 5)
92+
graph1.add_edge(4, 5)
93+
94+
graph1.print_adj_list()
95+
96+
path = []
97+
path = graph1.bfs(0, 5)
98+
print(path)
99+
100+
# Testing the `bfs_traversal()` method
101+
graph2 = Graph(5, directed=False)
102+
103+
graph2.add_edge(0, 1)
104+
graph2.add_edge(0, 2)
105+
graph2.add_edge(1, 2)
106+
graph2.add_edge(1, 4)
107+
graph2.add_edge(2, 3)
108+
109+
graph2.bfs_traversal(0)
110+
111+
if __name__=="__main__":
112+
main()

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /