Python: Graph、DFS、set、defaultdict - 更改字典大小时出错
Python: Graph, DFS, set, defaultdict - error in changing dictionary size
当我尝试使用深度优先方法打印断开连接的图形时出现此问题。
我正在使用 defaultdict
作为图形的邻接表表示。我知道如果一个键不在字典中,defaultdict
会添加它并提供您设置的任何默认值(在我的例子中是 list
)。
在您将此评论为重复之前,我已经阅读了帖子 and here。他们表明字典在迭代期间正在更改,但我不太了解我的特定情况。我没有从 defaultdict
弹出任何值。
代码改编自 GeeksForGeeks 但我决定对访问的顶点使用 set
而不是 list
并且我重命名了 DFSUtil
函数,DFSHelper
。此外,正在打印的图表与下面的图表相同,只是我添加了一个指向节点 4 的节点 5。我试图添加它以使图表真正断开连接。如果没有此附加条目,则不会产生错误。
这是我的代码:
from collections import defaultdict
class Graph:
def __init__(self):
self.graph = defaultdict(list)
def addEdge(self, u, v):
self.graph[u].append(v)
def DFSHelper(self, vertex, visited):
# recursively visit adjacent nodes
if vertex not in visited:# and vertex in self.graph:
visited.add(vertex)
print(vertex)
for neighbor in self.graph[vertex]:
self.DFSHelper(neighbor, visited)
def DFS(self): # for disconnected graph
visited = set()
# print(self.graph.keys())
for vertex in self.graph.keys():
if vertex not in visited:
self.DFSHelper(vertex, visited)
print('Visited : ', visited)
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.addEdge(5, 4) # disconnected graph - I added this edge myself
print(g.graph)
print("Following is DFS of a disconnected graph")
g.DFS()
我注意到当我更改 DFSHelper 中的第一行时:
if vertex not in visited:
到
if vertex not in visited and vertex in self.graph:
错误会消失,但我不明白为什么会这样。我的假设是在 defaultdict
中搜索不是键的顶点 4,并且由于 defaultdict
的默认操作是创建一个条目而不是 return 一个键错误, defaultdict
在迭代过程中被改变。但是,我看不到 4 是如何传递到函数 defaultdict
.
中的
这是错误的输出。
Following is DFS of a disconnected graph
0
1
2
3
5
4
Traceback (most recent call last):
File "depth-first-search-disconnected_graph.py", line 41, in <module>
g.DFS()
File "depth-first-search-disconnected_graph.py", line 25, in DFS
for vertex in self.graph.keys():
RuntimeError: dictionary changed size during iteration
注意正在打印的 4。
这是已解决错误的输出。
Following is DFS of a disconnected graph
0
1
2
3
5
Visited : {0, 1, 2, 3, 5}
当你到达4和5的边缘时,当代码到达for neighbor in self.graph[vertex]
时,你通过5的邻居。 5 的唯一邻居是 4,然后您以 4 为顶点递归调用该函数。在 DFSHelper
的下一次调用中,defaultdict 为 4 添加了一个条目,因为它丢失了。
只需在 for 循环之前添加您的条件 if vertex in self.graph
即可避免此错误。
当我尝试使用深度优先方法打印断开连接的图形时出现此问题。
我正在使用 defaultdict
作为图形的邻接表表示。我知道如果一个键不在字典中,defaultdict
会添加它并提供您设置的任何默认值(在我的例子中是 list
)。
在您将此评论为重复之前,我已经阅读了帖子 defaultdict
弹出任何值。
代码改编自 GeeksForGeeks 但我决定对访问的顶点使用 set
而不是 list
并且我重命名了 DFSUtil
函数,DFSHelper
。此外,正在打印的图表与下面的图表相同,只是我添加了一个指向节点 4 的节点 5。我试图添加它以使图表真正断开连接。如果没有此附加条目,则不会产生错误。
这是我的代码:
from collections import defaultdict
class Graph:
def __init__(self):
self.graph = defaultdict(list)
def addEdge(self, u, v):
self.graph[u].append(v)
def DFSHelper(self, vertex, visited):
# recursively visit adjacent nodes
if vertex not in visited:# and vertex in self.graph:
visited.add(vertex)
print(vertex)
for neighbor in self.graph[vertex]:
self.DFSHelper(neighbor, visited)
def DFS(self): # for disconnected graph
visited = set()
# print(self.graph.keys())
for vertex in self.graph.keys():
if vertex not in visited:
self.DFSHelper(vertex, visited)
print('Visited : ', visited)
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.addEdge(5, 4) # disconnected graph - I added this edge myself
print(g.graph)
print("Following is DFS of a disconnected graph")
g.DFS()
我注意到当我更改 DFSHelper 中的第一行时:
if vertex not in visited:
到
if vertex not in visited and vertex in self.graph:
错误会消失,但我不明白为什么会这样。我的假设是在 defaultdict
中搜索不是键的顶点 4,并且由于 defaultdict
的默认操作是创建一个条目而不是 return 一个键错误, defaultdict
在迭代过程中被改变。但是,我看不到 4 是如何传递到函数 defaultdict
.
这是错误的输出。
Following is DFS of a disconnected graph
0
1
2
3
5
4
Traceback (most recent call last):
File "depth-first-search-disconnected_graph.py", line 41, in <module>
g.DFS()
File "depth-first-search-disconnected_graph.py", line 25, in DFS
for vertex in self.graph.keys():
RuntimeError: dictionary changed size during iteration
注意正在打印的 4。
这是已解决错误的输出。
Following is DFS of a disconnected graph
0
1
2
3
5
Visited : {0, 1, 2, 3, 5}
当你到达4和5的边缘时,当代码到达for neighbor in self.graph[vertex]
时,你通过5的邻居。 5 的唯一邻居是 4,然后您以 4 为顶点递归调用该函数。在 DFSHelper
的下一次调用中,defaultdict 为 4 添加了一个条目,因为它丢失了。
只需在 for 循环之前添加您的条件 if vertex in self.graph
即可避免此错误。