标准的bfs实现类似于(由维基百科提供):
Breadth-First-Search(Graph, root):
create empty set S
create empty queue Q
root.parent = NIL
Q.enqueue(root)
while Q is not empty:
current = Q.dequeue()
if current is the goal
return current
for each node n that is adjacent to current:
if n is not in S:
add n to S
n.parent = current
Q.enqueue(n)
我想知道为什么在查看与当前相邻的邻居时,无法检查电流是否是目标。对于前者类似的东西:
Breadth-First-Search(Graph, root):
create empty set S
create empty queue Q
root.parent = NIL
if root is the goal
return root
Q.enqueue(root)
while Q is not empty:
current = Q.dequeue()
for each node n that is adjacent to current:
if n is the goal // check here instead
n.parent = current
return n
if n is not in S:
add n to S
n.parent = current
Q.enqueue(n)
这个想法是,一旦在邻居中找到它,你就会抓住这个词。您可以确保这是最短的路径,因为队列中的路径不可能已经包含路径,因为我们在它发生之前就已经捕获了该路径。
据我所知,这需要在while循环之前添加一个额外的检查,以查看root是否是目标,但除此之外,是否有一些原因bfs没有像这样实现?它在技术上应该更快吗?
答案 0 :(得分:1)
如果您对根进行检查,您的版本可以正常工作(您应该将其放在问题中)。
在某些情况下,您的方式会更快,在某些情况下会更慢。例如,如果存在某种惩罚(如额外的缓存未命中)以便两次访问每个节点的内容,它可能会更慢。
通常差异并不显着,人们只是因为代码更简单而第一种方式。
答案 1 :(得分:0)
我想我会进一步重构它。我注意到root没有直接添加到S中,这意味着它会在以后添加,然后再次检查。我在早期根返回后移动了S和Q的创建。切换while,这意味着root不必排入Q然后检查Q以查看root是否在其中然后将root出列。我将S检查移动到每个循环的第一个内部,因为该检查将阻止目标检查每次循环一次或多次,目标检查只会阻止S检查一次。它还让我删除了n.parent =当前代码行重复,没有帮助性能,但我不喜欢重复。
Breadth-First-Search(Graph, root):
root.parent = NIL
if root is the goal
return root
create empty set S
add root to S
create empty queue Q
current = root
while true
for each node n that is adjacent to current:
if n in S:
continue
n.parent = current
if n is the goal
return n
add n to S
Q.enqueue(n)
if Q empty
break
current = Q.dequeue()