The problem with your solution is that the function percorrer
does not have access to lista
, which is where you store the information about which vertices you have visited. You have to pass on this information from some way for the function that will make the recursion. I joined the functions, put some comments and made a more idiomatic code:
# encoding: utf-8
# A linha anterior permite usar acentos no nosso programa.
def gerar_caminhos(grafo, caminho, final):
"""Enumera todos os caminhos no grafo `grafo` iniciados por `caminho` e que terminam no vértice `final`."""
# Se o caminho de fato atingiu o vértice final, não há o que fazer.
if caminho[-1] == final:
yield caminho
return
# Procuramos todos os vértices para os quais podemos avançar…
for vizinho in G[caminho[-1]]:
# …mas não podemos visitar um vértice que já está no caminho.
if vizinho in caminho:
continue
# Se você estiver usando python3, você pode substituir o for
# pela linha "yield from gerar_caminhos(grafo, caminho + [vizinho], final)"
for caminho_maior in gerar_caminhos(grafo, caminho + [vizinho], final):
yield caminho_maior
# Exemplo de uso
G = {'A': ['B', 'C'], 'B': ['A', 'C', 'D'], 'C': ['A', 'B', 'D'], 'D': ['B', 'C']}
for caminho in gerar_caminhos(G, ['A'], 'D'):
# "print(caminho)" em python3
print caminho
(Ideone)
To avoid repetition, I use the operator in
from Python, which checks whether an object belongs to a list (or a set, or to the keys of a dictionary) - this means that I ignore the neighbors of the current vertex I’ve passed.
The other thing I do is use the yield
in my role - it is easier to illustrate what it does with a simpler example:
def LOST():
yield 4
yield 8
yield 15
yield 16
yield 23
yield 42
for n in LOST():
print n
The yield
works as if it were a return
, but thought to be used in a for
. The yield
, unlike the return
, does not interrupt function execution: it returns the value for the for
, let the for
do his job, and then go back to performing the function from where he left off.
The idea of recursive call to gerar_caminhos(grafo, caminho + [vizinho], final)
is that it is permitted to go to vizinho
starting from caminho[-1]
(the last element of caminho
); I seek all the ways that do this, return them to the function-mother (i.e. the function that called me), and repeat this to all neighbors who are no longer in the way (thus avoiding repetition).
I suppose you want to generate paths without repeated vertices (e.g. ['A', 'B', 'C', ’D'] would be legal but ['A', 'B', 'C', 'B', ’D'] would be prohibited)? What is the maximum number of vertices of this graph?
– user25930
@ctgPi Yes, there are not supposed to be repeated vertices. I am creating this function to help in another, and it makes no sense to have repeated vertices. This graph may have n vertices, but in the example I gave it has only 4.
– Diana Vasconcelos Ferreira
It has how to edit the question and post the code you have made so far (even with this problem of going through the graph infinitely)?
– user25930
@ctgPi Editei, already put the code!
– Diana Vasconcelos Ferreira