我正在尝试实现Graph和bfs(广度优先搜索)算法。 我有这个graph_object类:
class Vertex:
def __init__(self,id):
self.id=id #just a character representing each node/vertex name e.g. 'a', 'b'...
self.neighbors=[]
'''list of adjacent vertices. we call them neighbors.
d.neighbors=[b,c,g].
note that here we are talking about the Vertex objects b,c,g. Not their corresponding vertex IDS ('b', 'c' and 'g')
'''
self.parent=None
'''parent of a vertex depends on order of visit of the vertices in a graph.
calling the function bfs() on above graph will assign a.parent=None, b.parent=a , c.parent=d, d.parent=b, g.parent=d '''
def __str__(self):
return "{}:{}".format(self.id,self.get_neighbors()) #
def get_neighbors(self):
return [v.id for v in self.neighbors]
def get_id(self):
return self.id
def get_parent(self):
return self.parent
def add_neigbor(self,v):
self.neighbors.append(v)
class Graph:
def __init__(self):
self.vertices={}
self.num_vert=0
def get_vertex(self,v_id):
if v_id not in self.get_vertices():
return None
else:
return [v for v in self.vertices if v.id==v_id].pop(0) #to understand what happens here, refer to dict_exercise.py
def add_vertex(self,v_id):
if v_id not in self.get_vertices():
new=Vertex(v_id)
self.vertices[new]=new.neighbors
def add_edge(self,v1_id,v2_id):
if v1_id not in self.get_vertices():
self.add_vertex(v1_id)
if v2_id not in self.get_vertices():
self.add_vertex(v2_id)
#vertices with IDs v1_id and v2_id are now guaranteed to exist in graph, we get the corresponding vertex objects v1 and v2
v1=self.get_vertex(v1_id)
v2=self.get_vertex(v2_id)
if v2_id not in v1.get_neighbors():
v1.add_neigbor(v2)
if v1_id not in v2.get_neighbors():
v2.add_neigbor(v1)
def get_vertices(self):
return [v.id for v in self.vertices.keys()]
我也在使用一个包含bfs算法的测试类:
from graph_object import *
def bfs(g, s):
explored, queue = [], [s]
while queue:
current_vertex = queue.pop(0)
if current_vertex not in explored:
explored.append(current_vertex)
neighbors = g[current_vertex]
queue += neighbors
return explored
graph = Graph()
graph.add_edge('a', 'b')
graph.add_edge('b', 'c')
graph.add_edge('c', 'd')
graph.add_edge('d', 'b')
graph.add_edge('d', 'g')
print("List of vertex IDs in graph:")
vertices = graph.get_vertices() #returns graph vertices as a list of vertex IDs
print(vertices)
vertices_dict = graph.vertices
print("Vertex information in format <vertex id>:<list of neighbors>")
for vertex in vertices_dict.keys():
print(vertex)
print("BFS(a) explored the elements in graph in the order:")
print(*bfs(graph, 'a'), sep=', ')
当我运行代码时,我收到此错误:
Traceback (most recent call last):
List of vertex IDs in graph:
File "C:/Users/rawsly/PycharmProjects/MiniProject/test.py", line 40, in <module>
['a', 'b', 'c', 'd', 'g']
print(*bfs(graph, 'a'), sep=', ')
Vertex information in format <vertex id>:<list of neighbors>
File "C:/Users/rawsly/PycharmProjects/MiniProject/test.py", line 10, in bfs
a:['b']
neighbors = g[current_vertex]
b:['a', 'c', 'd']
TypeError: 'Graph' object is not subscriptable
我知道在bfs中为探索使用 set 结构会更好,但后来我意识到输出没有被排序,因为 set 结构没有订购。因此我想改用 list 。另一方面,使用 dequeue 也更有效但是现在我不考虑效率。我稍后会改进代码,但首先,我想解决这个错误。
答案 0 :(得分:2)
您如何访问图表是错误的。它不是一本字典,所以它不知道如何以你现在编码的方式获得一个项目。您还将遇到队列问题,因为这不是您将项目添加到列表的方式。您可以使用图表类中的顶点getter,并添加到队列列表中,您可以使用append。
def bfs(g, s):
explored, queue = [], [s]
while queue:
current_vertex = queue.pop(0)
print(current_vertex)
if current_vertex not in explored:
explored.append(current_vertex)
neighbors = g.get_vertex(current_vertex).get_neighbors()
queue.extend(neighbors)
return explored
编辑:我看到你想扩展队列而不是追加。您还想使用get_neighbors函数以及获取顶点。
答案 1 :(得分:0)
替换
neighbors = g[current_vertex]
与
neighbors = g.get_vertex(current_vertex).get_neighbors()