【问题标题】:Expanding a path from a graph从图中扩展路径
【发布时间】:2011-02-23 01:25:41
【问题描述】:

我知道这种结构有一些模块,但我喜欢并且更喜欢自己了解事情的真正运作方式。 所以......我正在尝试从图表中扩展路径,例如:

g = dict(
    s=['a','d','s'],
    a=['s','d','b'],
    d=['s','a','e'],
    b=['a','e','c'],
    e=['d','b','f'],
    f=['e','g'],
    c=['b'],
    g=['f'])

到目前为止,我可以看到给定节点的邻居:

def vecinosDe(n = ''):
    return g[n]

我希望每次调用一个给定参数的函数时,一个图形节点,返回一个连接到给定参数的其他节点的列表。
然后将给定、创建的相同列表输入到相同的函数以返回连接到给定列表图节点的节点,并连续返回直到它到达“g”节点。
我也知道我需要检查连接到给定节点的节点是否有任何递归(循环)。

这是我目前的代码:

def expandir(n = '', lista = []):
    lista.append([n]) #or lista = lista + [n]?
    for v in g[n]:
        for i in range(len(lista)): #?
            lista[i].append(v)
    return lista

这就是发生的事情,我知道这不好,哈哈。

>>> expandir('s')
[['s', 'd', 'a', 's']]
>>> expandir('d')
[['S', 'D', 'A', 'S', 'S', 'A', 'E'], ['D', 'S', 'A', 'E']]

在第二个for循环中的某些部分代码中,我认为我应该检查是否有一个节点等于我要扩展的节点,即给定的节点。这就是我卡住的地方。
试试这个?

if n == v:  #?

另外我认为这可能需要某种递归,对吧?但我想要一些技巧来继续拼图。 :P

我应该返回一个列表,一个列表列表吗?...如何? :S
有小费吗? :)
在此先感谢

【问题讨论】:

  • 顺便说一句,你也可以把graph写成graph = dict(s='ads', a='sdb', d='sae', b='aec', e='dbf', f='eg', c='b', g='f')。字符串也是可迭代的。

标签: python graph


【解决方案1】:

这是对@tangentstorm's answer 的修改,它避免使用生成器引发显式异常:

def pathiter(adjacent_vertexes, start, end, path=None):
    if path is None: path = (start,)

    for vertex in adjacent_vertexes[start]:
        if vertex == end:
            yield path + (vertex,)
        elif vertex not in path:
            for p in pathiter(adjacent_vertexes, vertex, end, path + (vertex,)):
                yield p

例子:

end = 'g'
for v in g:
    path = next(pathiter(g, v, end), None)
    if path is not None:
        print ' → '.join(path)
    else:
        print "no path between %s and %s" % (v, end)

输出

a → s → d → e → f → g
c → b → a → s → d → e → f → g
b → a → s → d → e → f → g
e → f → g
d → s → a → b → e → f → g
g → f → g
f → g
s → a → d → e → f → g

您可以打印所有路径:

for v in graph:
    print "%s ⇢ %s:" % (v, end)
    path = None
    for path in pathiter(graph, v, end):
        print '\t'+' → '.join(path)
    if path is None:
        print "no path between %s and %s" % (v, end)

输出

a ⇢ g:
    a → s → d → e → f → g
    a → d → e → f → g
    a → b → e → f → g
c ⇢ g:
    c → b → a → s → d → e → f → g
    c → b → a → d → e → f → g
    c → b → e → f → g
b ⇢ g:
    b → a → s → d → e → f → g
    b → a → d → e → f → g
    b → e → f → g
e ⇢ g:
    e → f → g
d ⇢ g:
    d → s → a → b → e → f → g
    d → a → b → e → f → g
    d → e → f → g
g ⇢ g:
    g → f → g
f ⇢ g:
    f → g
s ⇢ g:
    s → a → d → e → f → g
    s → a → b → e → f → g
    s → d → a → b → e → f → g
    s → d → e → f → g

【讨论】:

    【解决方案2】:

    这是我的看法:

    graph = g # from your code
    
    def findPath(graph, node, path=tuple(), end='g'):
        for key in graph[node]:
            next = path + (key,)
            if key == end:
                raise Exception("Found it! Path is: %s" % '.'.join(path))
            elif key in path:
                pass # avoid loops
            else:
                # print next # if you want to see what it's doing
                findPath(graph, key, next, end)
        else: # no break/raise at this level
            if len(path) == 0: print "no path found."
    
    findPath(graph, 's')
    

    我认为您的主要问题 [除了真正难以理解的变量名 :)] 是您的路径 (lista) 的默认参数为 []。这很糟糕,因为default arguments are mutable

    另外我认为这可能需要某种递归,对吧?但我想要一些技巧来继续拼图。 :P

    是的,当你看到一棵树时,想想递归。 :)

    【讨论】:

      【解决方案3】:

      http://eloquentjavascript.net/chapter7.html 中有一个非常好的路径搜索示例。当然,它会教你用 javascript 一步一步地开发这个算法。这是一个很好的阅读理解它在做什么。

      【讨论】:

        猜你喜欢
        • 2020-02-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-05-21
        • 2019-09-01
        • 1970-01-01
        • 1970-01-01
        • 2017-06-22
        相关资源
        最近更新 更多