从图中展开路径

发布于 2024-10-18 10:55:33 字数 1200 浏览 0 评论 0原文

我知道有此类结构的模块,但我喜欢并且更喜欢自己学习事物的真正工作原理。 所以......我一直在尝试从图中扩展路径,例如: graph:

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
有什么建议吗? :)
提前致谢

I know there are modules for this type of structure, but I like and prefer to learn how things really works by myself.
So... I've being trying to expand a path from a graph, such as for example:
graph:

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'])

So far I can see the neighbors of a given node with:

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

I want to each time I call a function that has one argument given, a graph node, returns a list of the other nodes connected to that one given.
Then enter that same list given, created, to that same function to return the nodes connected to that list graph nodes given, and consecutively until it reaches to the 'g' node.
I also know that I need to check if the node connected to the node given has any recursion(loop).

Here's the code I have so far:

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

This is what happens, which I know it's not good, lol.

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

In some part of the code within the second for loop I think I should check if there is a node equal to the node I want to expand, the node given. Here's where I get stuck.
Try this?

if n == v:  #?

Also I'm thinking that this may need some kind of recursion, right? But I would like some tips to keep putting the puzzle together. :P

Should I return a list, a list of lists?... how? :S
Any tips? :)
thanks in advance

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

三五鸿雁 2024-10-25 10:55:33

这是对 @tangentstorm 的答案的修改,避免引发显式异常通过使用生成器:

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

Here's a modification of @tangentstorm's answer that avoids raising explicit exception by using a generator:

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

Example:

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)

Output

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

You could print all paths:

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)

Output

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
墨离汐 2024-10-25 10:55:33

这是我的看法:

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)有默认参数 []。这很糟糕,因为默认参数是可变的

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

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

Here's my take on it:

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')

I think your main problem [aside from really unreadable variable names :)] is that your path (lista) has a default argument of []. This is bad because default arguments are mutable

Also I'm thinking that this may need some kind of recursion, right? But I would like some tips to keep putting the puzzle together. :P

Yep, when you see a tree, think recursion. :)

溺渁∝ 2024-10-25 10:55:33

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

There is a very good sample in javascript to path searching in http://eloquentjavascript.net/chapter7.html. It teaches you, of course, in javascript, to develop step by step this very algorithm. Its a good reading to understand what it's doing.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文