拓扑排序,递归,使用生成器

时间:2020-03-06 14:29:16  来源:igfitidea点击:

数据:依赖项列表,已被验证为非循环。所以在这里," a"取决于" b"," c"(c取决于d),等等。

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

我想有一个自上而下的递归解决方案,可以说找到从
'a':a,c,d,e,g,f,b

因此,现在(非发电机解决方案):

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

显然,这是非常薄弱的​​:)我一直在想如何在其中获得收益,我想感谢所有py-foo你们都可以带来的收益。

解决方案

试试这个:

#!/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

给我

steve@rei:~/code/tmp
$ python recur.py
a
c
d
e
g
f
b

这两个答案都给出相同的结果,但是如果我们从'b'中添加对'c'的依赖关系(这不会引入循环,则如果我对问题的理解是正确的,则对给定图的简单更改给出错误的答案)该图是有向的),输出为:
一种
C
d
Ë
G
F
b
d
Ë
G
F
`

这不是完全有帮助。试试这个小的变化,它可以跟踪图形中的哪些节点已经被访问过:

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