Как вы отслеживаете путь поиска в ширину, например, в следующем примере:
При поиске ключа 11
верните самый короткий список, соединяющий с 1 по 11.
[1, 4, 7, 11]
python
algorithm
graph
breadth-first-search
Кристофер Маркиета
источник
источник
Ответы:
Сначала вам следует взглянуть на http://en.wikipedia.org/wiki/Breadth-first_search .
Ниже представлена быстрая реализация, в которой я использовал список списка для представления очереди путей.
Другой подход заключался бы в сохранении сопоставления каждого узла с его родителем и при проверке соседнего узла записывать его родительский узел. Когда поиск завершен, просто проследите в обратном направлении в соответствии с родительским отображением.
Приведенные выше коды основаны на предположении, что циклов нет.
источник
node==end
), добавьте этот путь в другой список, который будет содержать все пути, которые вы нашли, а затемcontinue
вместоreturn
. Если вы используете посещенный набор для предотвращения циклов, никогда не добавляйте конечный узел в посещаемый набор (иначе только один путь может иметь этот конечный узел).Мне очень понравился первый ответ Цяо! Единственное, чего здесь не хватает, - это пометить вершины как посещенные.
Зачем нам это нужно?
Представим себе, что есть еще один узел номер 13, подключенный к узлу 11. Теперь наша цель - найти узел 13.
После небольшого запуска очередь будет выглядеть так:
Обратите внимание, что есть ДВА пути с номером узла 10 в конце.
Это означает, что пути от узла номер 10 будут проверены дважды. В данном случае это выглядит не так уж плохо, потому что узел номер 10 не имеет дочерних узлов ... Но это может быть очень плохо (даже здесь мы проверим этот узел дважды без причины ...)
Узла номер 13 нет в эти пути, так что программа не вернется, пока не достигнет второго пути с номером 10 в конце .. И мы перепроверим это ..
Нам не хватает только набора, чтобы отмечать посещенные узлы и не проверять их снова ..
Это код qiao после модификации:
Результатом программы будет:
Без лишних перепроверок ..
источник
collections.deque
дляqueue
как list.pop (0) ПОНЕСТИO(n)
движений памяти. Кроме того, для потомков, если вы хотите сделать DFS, просто установите, иpath = queue.pop()
в этом случае переменнаяqueue
фактически действует какstack
.Очень простой код. Вы продолжаете добавлять путь каждый раз, когда обнаруживаете узел.
источник
Я подумал, что попробую написать это ради удовольствия:
Если вам нужны циклы, вы можете добавить это:
источник
Мне нравится как первый ответ @Qiao, так и добавление @Or. Ради меньшей обработки я хотел бы добавить к ответу Ор.
В ответе @ Or отслеживание посещенного узла - это здорово. Мы также можем позволить программе выйти раньше, чем сейчас. В какой-то момент в цикле for
current_neighbour
должен бытьend
, и как только это произойдет, будет найден кратчайший путь, и программа сможет вернуться.Я бы изменил метод следующим образом, уделив особое внимание циклу for
Вывод и все остальное будет таким же. Однако обработка кода займет меньше времени. Это особенно полезно для больших графиков. Надеюсь, это кому-то поможет в будущем.
источник