递归函数,用于计算图形中从头到尾的简单路径

时间:2019-06-13 13:21:08

标签: python recursion graph

我编写了一个递归函数,以给定的图边列表作为元组在图中找到一条简单路径(只有一条路径)。例如:

edges = [(0, 10),(2, 16),(4, 5),(6, 24),(7, 6),(8, 23),(9, 25),(10, 14),(11, 1),(12, 19),(13, 22),(14, 15),(15, 11),(16, 7),(17, 21),(18, 13),(19, 17),(20, 8),(21, 3),(22, 20),(23, 12),(24, 9),(25, 18)]

def get_path(sol, start, end):
    out = []
    for i,j in sol:
        if i == start:
            out.append(i)
            out += get_path(sol, j, end)
        if j == end:
            out.append(j)
    return out

但是,如果我无法在返回列表中正确获取结束节点。如果删除第7行和第8行,则最后一个节点将不出现在我的解决方案中,并且如果代码中包含这些行,则我的解决方案将获得多个结束节点。例如:

get_path(edges, 2, 3)
path = [2, 16, 7, 11, 15, 14, 10, 22, 13, 18, 25, 21, 17, 19, 12, 9, 24, 6, 8, 20, 23]

我们可以看到结束节点是3,它应该是列表的最后一个元素。非常感谢您的投入。谢谢

2 个答案:

答案 0 :(得分:2)

您可以使用networkX。您可以从边缘定义网络并获得两个给定节点之间的简单路径。我正在使用nx.shortest_simple_paths,但是您可以使用all_simple_paths来全部获取它们:

import networkx as nx

G=nx.Graph()
G.add_edges_from(edges)
next(nx.shortest_simple_paths(G, 2, 3))
# [2, 16, 7, 6, 24, 9, 25, 18, 13, 22, 20, 8, 23, 12, 19, 17, 21, 3]

答案 1 :(得分:0)

您的代码中的每个递归调用都会进行一次迭代,其中j == end为真,因此您确实会多次添加它:与递归深度一样多。

如果将结束条件放在循环之外,效果会更好,如下所示:

if start == end:
    return [start]

因此,只需稍作修改,您的代码将如下所示:

def get_path(sol, start, end):
    if start == end:
        return [start]
    out = []
    for i,j in sol:
        if i == start:
            out.append(i)
            out += get_path(sol, j, end)
    return out

其他一些评论:

  • 您可以一次性在if块中执行两个列表操作:

      out += [i] + get_path(sol, j, end)
    
  • 遍历每个列表中的完整列表效率非常低 递归调用。最好先建一个键控的字典 按起始编号。这样一来,您不必反复查找 相应的边缘。

  • 似乎您的代码期望图形是一个链,没有任何 有2个或更多输出边缘的节点。如果发生这种情况,if i == start:块将执行多次,导致输出尴尬。对于此类情况,也不太困难

代码:

from collections import defaultdict 

def get_path(sol, start, end):
    # Transform to dict
    d = defaultdict(list)
    for i,j in sol:
        d[i] += [j]

    def recur(start):
        if start == end:
            return [start]
        for nxt in d[start]:
            path = recur(nxt)
            if path is not None: 
                return [start] + path
    return recur(start)

edges = [(0, 10),(2, 16),(4, 5),(6, 24),(7, 6),(8, 23),(9, 25),(10, 14),
         (11, 1),(12, 19),(13, 22),(14, 15),(15, 11),(16, 7),(17, 21),
         (18, 13),(19, 17),(20, 8),(21, 3),(22, 20),(23, 12),(24, 9),(25, 18)]

path = get_path(edges, 2, 3)
print (path)