2017-08-10 1 views
0

J'essaie fondamentalement de mieux comprendre la récursivité avec cet exemple. Regardons l'algorithme DFS suivant qui renvoie tous les nœuds connectés au nœud racine de base. Le "graphe" dans ce cas est défini comme une liste de tuples d'arêtes entre sommets.Résultats intermédiaires dans une fonction DFS récursive - Python

def dfs(graph,node,dfs_visited): 
    if node not in dfs_visited: 
     dfs_visited.append(node) 

     #find next node to go 
     potential_paths = [i for i in graph if node in i] 
     new_nodes = [node_ for path in potential_paths for node_ in 
        path if node_ !=node] 
     for n in new_nodes: 
      dfs(graph,n,dfs_visited) 
    return dfs_visited 

Par exemple, si le graphique était

graph = [(0, 1),(0, 2),(1, 2),(3, 4),(4,5)] 

le résultat de démarrage au niveau du noeud 0 serait

dfs(graph,0,[]) 
[0,1,2] 

Ce que je suis curieux de savoir dans ce cas est que cela est le résultat du "retour" d'un seul des appels récursifs. Évidemment, le code fonctionne comme je le souhaitais et je suis d'accord avec le résultat, mais je suis juste curieux de savoir où va l'intermédiaire "retourne". Par exemple, lorsque nous courons la même fonction avec une instruction d'impression ajouté juste avant la déclaration de retour, nous obtenons le résultat suivant:

dfs(graph,0,[]) 
returning [0, 1] 
returning [0, 1, 2] 
returning [0, 1, 2] 
returning [0, 1, 2] 
returning [0, 1, 2] 
returning [0, 1, 2] 
returning [0, 1, 2] 

Alors, comment Python savoir lequel d'entre eux est la sortie réelle de la fonction? Est-ce juste le dernier?

Répondre

1

Dans cette ligne où vous appelez la fonction récursive:

for n in new_nodes: 
    dfs(graph,n,dfs_visited) 

est où la valeur de retour des extrémités imbriquer vers le haut. Vous n'attribuez cette valeur à aucune variable, aussi python l'oublie dès qu'il passe à l'itération suivante. Vous devriez obtenir (presque) la même sortie que ce que vous avez imprimé au-dessus en utilisant l'instruction d'impression suivante:.

for n in new_nodes: 
    ret = dfs(graph,n,dfs_visited) 
    print(ret) 

(L'exception est la valeur retournée par l'appel initial, qui ne sera pas imprimé Vous devrait avoir une ligne de moins de [0, 1, 2] que ci-dessus.)

+0

merci pour la réponse. J'ai effectivement une question de suivi. J'ai donc essayé aussi d'assigner l'appel récursif à dfs_visited lui-même, et la fonction se comporte exactement de la même manière. Alors qu'est-ce qui se passe ici? La variable dfs_visited se comportait auparavant presque comme une variable globale, alors est-ce la raison pour laquelle cela n'a pas d'importance si nous ne mettons pas à jour la variable à chaque itération de la boucle? – user4505419

+1

Cela n'a pas d'importance, car vous ne créez qu'un seul objet liste (lorsque vous utilisez [] dans l'appel d'origine), puis passez des références à celui-ci. Donc, toutes les mentions de 'dfs_visited' dans votre code font référence au même conteneur - l'assignation de la valeur de retour (' dfs_visited') à la variable 'dfs_visited' remplace le pointeur par lui-même. – nengel