通过python中的递归生存列表的麻烦;在图表

时间:2016-12-04 04:04:55

标签: python list recursion graph

我正在编写一个python程序,它接受一个完全连接的图形(你可以从任何其他节点转到图形上的任何节点)并找到该图形上比给定最大距离短的所有可能路径。

这是我到目前为止编码的内容:

def find_all_routes (cur_node, graph, willing_to_travel, visited, routesdict):
    """ Finds all routes possible within a certain distance.
    inputs
        cur_node: a dictionary with n entries, each of which is the distance to the nth
            dictionary in graph.
        graph: a list of n dictionaries, each of which contains n entries, each of which
            is the distance to the nth item in the list.
        willing_to_travel: the maximum distance we are willing to travel.
        visited: initialized as an empty list, will be populated nodes we've been to.
        all_routes: initialized as an empty list.
    Affects:
        all_routes is populated with every route permutation that can be traveled in under willing_to_travel distance.
    """
    #Add our current location to the visited list.
    for i in cur_node:
        if cur_node[i] == 0:
            visited.append(graph[i])

    # Add the current route to the dictionary.
    entry_no = len(routesdict)
    routesdict[entry_no] = visited
    print ("routesdict", routesdict)            # Just for diagnostic purposes.

    # Recursion with other nodes we can reach as the new start node.
    for i in cur_node:                               # For every place in the dictionary
        if graph[i] not in visited:                  # if we have not been there
            if cur_node[i] <= willing_to_travel:     # And if we can afford to go there
                find_all_routes(graph[i], graph, willing_to_travel - cur_node[i], visited, routesdict)

    return routesdict

def main():

    graph = [
        {0: 0.00, 1: 0.12, 2: 0.10},
        {0: 0.12, 1: 0.00, 2: 0.22},
        {0: 0.10, 1: 0.22, 2: 0.00}]

    max_distance = 10.0
    been_to = []
    routesdict = dict()

    routes = find_all_routes (graph[0], graph, max_distance, been_to, routesdict)

print ("Final output: ", routes)

if __name__ == "__main__":
    main()

这个输出是:

routesdict:    {0: [{0: 0.0, 1: 0.12, 2: 0.1}]}
routesdict:    {0: [{0: 0.0, 1: 0.12, 2: 0.1}, {0: 0.12, 1: 0.0, 2: 0.22}], 1: [{0: 0.0, 1: 0.12, 2: 0.1}, {0: 0.12, 1: 0.0, 2: 0.22}]}
routesdict:    {0: [{0: 0.0, 1: 0.12, 2: 0.1}, {0: 0.12, 1: 0.0, 2: 0.22}, {0: 0.1, 1: 0.22, 2: 0.0}], 1: [{0: 0.0, 1: 0.12, 2: 0.1}, {0: 0.12, 1: 0.0, 2: 0.22}, {0: 0.1, 1: 0.22, 2: 0.0}], 2: [{0: 0.0, 1: 0.12, 2: 0.1}, {0: 0.12, 1: 0.0, 2: 0.22}, {0: 0.1, 1: 0.22 , 2: 0.0}]}
Final output:  {0: [{0: 0.0, 1: 0.12, 2: 0.1}, {0: 0.12, 1: 0.0, 2: 0.22}, {0: 0.1, 1: 0.22, 2: 0.0}], 1: [{0: 0.0, 1: 0.12, 2: 0.1}, {0: 0.12, 1: 0.0, 2: 0.22}, {0: 0.1, 1: 0.22, 2: 0.0}], 2: [{0: 0.0, 1: 0.12, 2: 0.1}, {0: 0.12, 1: 0.0, 2: 0.22}, {0: 0.1, 1:0.22, 2: 0.0}]}

这很丑陋,但是根据我们访问的节点重新编写它,就像这样:

routesdict [0]
routesdict [0, 1] [0, 1]
routesdict [0, 1, 2]  [0, 1, 2] [0, 1, 2]
Final out: [0, 1, 2]  [0, 1, 2] [0, 1, 2]

对于三节点图,如果最大距离足够高以完成每个可能的路径,我希望输出看起来更像这样:

All possible routes*: [0], [0,1], [0,1,2], [0,2], [0,2,1]
*If we must start at node 0.

===============

现在,我认为我看到了问题,但我无法通过解决它来思考。问题是我保持列表的“访问”的身份,而不是扯掉“访问”的当前值,然后继续使用它。

因此,第一次通过递归,routesdict [0]被定义为“被访问”,并且它正确地将节点[0]作为第一个路由。但是当访问被更改时,routesdict [0]会更新,现在它会显示[0,1]。

这是阻止函数执行我想要的递归的原因,这就是为什么它给了我三条可能的路径而不是我期望的五条路径。

那么,在进行更深入的递归时,是否有一种很好的方法可以保留我的“访问”列表,但是没有将该列表追溯适用于世界其他地方?

感谢阅读!

编辑:

我已经通过将行更改为

来解决了将路由引入routesdict的问题
routesdict[entry_no] = visited[:]

但是我对于没有访问列表打破我的递归更加无能为力!

1 个答案:

答案 0 :(得分:0)

你的两个问题都是由同一件事引起的:Python通过引用传递列表,而不是按值传递。

首先,这意味着什么,简而言之:

当您使用foo(a)作为int调用a时,在foo()内,您只需获取a的值,而不是其在内存中的实际位置。您在论文上写了a,并显示foo(),&#34;这是a,将其写下来。&#34;

但是,当您使用bar(b)作为列表或对象调用b时,您没有获得b的值,您将获得b本身,内存地点。您的论文仍然有b,但是你对bar()说,&#34;嘿,b非常复杂,可能不值得复制到新的纸张上。你可以分享我的论文。&#34;这非常适合让您的程序变得非常慢,但是 - 正如您所经历的那样 - 这意味着bar()所做的任何更改都会使b更改b

要解决您的问题,您应该传递您不想要更改的对象的副本。在将visited添加到routesdict时,您已经明白了这一点,但实际上您应该这样做

find_all_routes(graph[i], graph, willing_to_travel - cur_node[i], visited[:], routesdict)

这意味着每次拨打find_all_routes()都会获得visited的个人副本。