Мне очень понравился первый ответ Цяо!
Единственное, чего здесь не хватает, это пометить вершины как посещенные.
Почему мы должны это сделать?
Давайте представим, что к узлу 11 подключен еще один узел № 13. Теперь наша цель - найти узел 13.
После небольшой пробежки очередь будет выглядеть так:
[[1, 2, 6], [1, 3, 10], [1, 4, 7], [1, 4, 8], [1, 2, 5, 9], [1, 2, 5, 10]]
Обратите внимание, что есть ДВЕ пути с узлом № 10 в конце.
Это означает, что пути от узла № 10 будут проверены дважды. В этом случае это не выглядит так плохо, потому что у узла № 10 нет дочерних элементов ... Но это может быть очень плохо (даже здесь мы проверим этот узел дважды без причины ..)
Узел № 13 не находится в этих путях, поэтому программа не вернется, пока не достигнет второго пути с узлом № 10 в конце ... И мы еще раз проверим его.
Все, что нам не хватает, - это набор для отметки посещенных узлов, а не для их повторной проверки.
Это код Цяо после модификации:
graph = {
1: [2, 3, 4],
2: [5, 6],
3: [10],
4: [7, 8],
5: [9, 10],
7: [11, 12],
11: [13]
}
def bfs(graph_to_search, start, end):
queue = [[start]]
visited = set()
while queue:
# Gets the first path in the queue
path = queue.pop(0)
# Gets the last node in the path
vertex = path[-1]
# Checks if we got to the end
if vertex == end:
return path
# We check if the current node is already in the visited nodes set in order not to recheck it
elif vertex not in visited:
# enumerate all adjacent nodes, construct a new path and push it into the queue
for current_neighbour in graph_to_search.get(vertex, []):
new_path = list(path)
new_path.append(current_neighbour)
queue.append(new_path)
# Mark the vertex as visited
visited.add(vertex)
print bfs(graph, 1, 13)
Вывод программы будет:
[1, 4, 7, 11, 13]
Без ненужных перепроверок ..