2008-09-20 8 views
3

Données: une liste de dépendances, déjà vérifiée pour être acyclique. Voici donc, 'a' dépend 'b', 'c' (c dépend d), etc ...Tri topologique, récursif, utilisant des générateurs

A = { 'a' : dict(b=1, c=1), 
    'c' : dict(d=1), 
    'd' : dict(e=1,f=1,g=1), 
    'h' : dict(j=1) 
    } 

Je voudrais avoir un haut vers le bas, la solution récursive pour disons, trouver la chaîne à partir de 'a': a, c, d, e, g, f, b

Ainsi, en ce moment (une solution non générateur):

def get_all(D,k): 
    L = [] 
    def get2(D,k): 
     L.append(k) 
     for ii in D.get(k,[]): 
      get2(D, ii) 
    get2(D,k) 
    return L 

de toute évidence, cela est assez faible :) Je me suis cogné la tête sur la façon d'obtenir des rendements à l'intérieur, et j'apprécierais tout py-foo y'all peut apporter à cela.

Répondre

4

Essayez ceci:

#!/usr/bin/env python 

def get_all(D, k): 
    yield k 
    for ii in D.get(k, []): 
     for jj in get_all(D, ii): 
      yield jj 

A = { 'a' : dict(b=1, c=1), 
    'c' : dict(d=1), 
    'd' : dict(e=1,f=1,g=1), 
    'h' : dict(j=1) 
    } 

for ii in get_all(A,'a'): 
    print ii 

Ça me donne

 
[email protected]:~/code/tmp 
$ python recur.py 
a 
c 
d 
e 
g 
f 
b 
+0

Merci! Je n'ai clairement pas eu assez de café ce matin. –

+0

Pas de problèmes :-) Peut-être que c'est le cas que j'ai pris trop de café aujourd'hui: P – freespace

+0

Quelqu'un at-il dit café? :) Bonne réponse, espace libre. –

6

Les deux réponses donnent le même résultat, mais si ma lecture de la question est correcte donne la mauvaise réponse à une simple modification à la donnée graphe - si vous ajoutez une dépendance à 'c' de 'b' (qui n'introduit pas un cycle comme le graphique est dirigé) la sortie est: a c d e g f b d e g f

ce qui n'est pas totalement utile . Essayez cette petite variation, qui garde la trace des noeuds du graphique qui ont déjà été visités:

def get_all(D, k, seen=None): 
    if not seen: 
     seen = set() 
    if k not in seen: 
     seen.add(k) 
     yield k 
     for ii in D.get(k, []): 
      for jj in get_all(D, ii, seen): 
       yield jj 
+1

Donc, le problème avec cette méthode est que la longueur de stockage peut à nouveau gonfler jusqu'à N, où N est le nombre de nœuds dans le graphique. C'est une variation très utile cependant. Pour cette application particulière, cela ne me dérange pas de revisiter les chaînes. –