Como você rastreia o caminho de uma pesquisa em amplitude, de modo que no exemplo a seguir:
Se estiver procurando por chave 11
, retorne a lista mais curta conectando de 1 a 11.
[1, 4, 7, 11]
python
algorithm
graph
breadth-first-search
Christopher Markieta
fonte
fonte
Respostas:
Você deve consultar http://en.wikipedia.org/wiki/Breadth-first_search primeiro.
Abaixo está uma implementação rápida, na qual usei uma lista de lista para representar a fila de caminhos.
Outra abordagem seria manter um mapeamento de cada nó para seu pai e, ao inspecionar o nó adjacente, registrar seu pai. Quando a pesquisa for concluída, basta fazer o backtrace de acordo com o mapeamento pai.
Os códigos acima são baseados no pressuposto de que não há ciclos.
fonte
Gostei muito da primeira resposta de qiao! A única coisa que falta aqui é marcar os vértices como visitados.
Por que precisamos fazer isso?
Vamos imaginar que há outro nó de número 13 conectado a partir do nó 11. Agora, nosso objetivo é encontrar o nó 13.
Depois de um pouco de execução, a fila ficará assim:
Observe que existem DOIS caminhos com o número de nó 10 no final.
O que significa que os caminhos do nó número 10 serão verificados duas vezes. Neste caso, não parece tão ruim porque o nó número 10 não tem nenhum filho .. Mas pode ser muito ruim (mesmo aqui vamos verificar esse nó duas vezes sem motivo ..) O
nó número 13 não está em esses caminhos para que o programa não retorne antes de chegar ao segundo caminho com o nó número 10 no final .. E vamos verificar novamente ..
Só falta um conjunto para marcar os nós visitados e não verificá-los novamente.
Este é o código de qiao após a modificação:
O resultado do programa será:
Sem as verificações desnecessárias ..
fonte
collections.deque
paraqueue
as list.pop (0) incorrer emO(n)
movimentos de memória. Além disso, para o bem da posteridade, se você quiser fazer DFS apenas definapath = queue.pop()
, nesse caso, a variávelqueue
realmente atua como umstack
.Código muito fácil. Você continua acrescentando o caminho cada vez que descobre um nó.
fonte
Pensei em tentar codificar isso por diversão:
Se você quiser ciclos, pode adicionar isto:
fonte
Eu gosto tanto da primeira resposta de @Qiao quanto da adição de @ Or. Para um pouco menos de processamento, gostaria de acrescentar à resposta de Or.
Na resposta de @ Or, manter o controle do nó visitado é ótimo. Também podemos permitir que o programa saia mais cedo do que está atualmente. Em algum ponto do loop for, o
current_neighbour
terá que ser oend
e, quando isso acontecer, o caminho mais curto é encontrado e o programa pode retornar.Eu modificaria o método conforme a seguir, preste atenção ao loop for
A saída e tudo o mais serão os mesmos. No entanto, o código levará menos tempo para ser processado. Isso é especialmente útil em gráficos maiores. Espero que isso ajude alguém no futuro.
fonte