在python中,列表通过递归生存的问题;在图上查找所有可能的路由
我正在编写一个python程序,它获取一个完全连接的图(您可以从任何其他节点转到图上的任何节点),并在该图上查找所有可能的路由,这些路由短于给定的最大距离 这是我到目前为止编写的代码:在python中,列表通过递归生存的问题;在图上查找所有可能的路由,python,list,recursion,graph,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
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]
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]
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[:]
但是我更不知道访问列表是否会破坏我的递归 两个问题都是由同一件事引起的:Python通过引用而不是通过值来传递列表 首先,简而言之,这意味着什么: 当用
a
作为int调用foo(a)
时,在foo()
内部,只得到a
的值,而不是它在内存中的实际位置。你的论文上写了a
,你展示了foo()
,“这是a
,把它写下来。”
但是,当您使用b
作为列表或对象调用bar(b)
时,您不会得到b
的值,而是得到b
本身,即内存位置。你的论文上仍然有b
,但是你对bar()
,“嘿,b
非常复杂,可能不值得复制到一张新的纸上。你可以分享我的论文。”这对于防止你的程序变得非常慢很好,但是——正如你所经历的那样——这意味着任何更改bar()
make tob
changeb
无处不在
要解决问题,应该传递不希望更改的对象的副本。在将访问的添加到路由dict
时,您已经了解到了这一点,但实际上您应该这样做
find_all_routes(graph[i], graph, willing_to_travel - cur_node[i], visited[:], routesdict)
这意味着对find_all_routes()
的每次调用都会得到它自己的、已访问的的个人副本这两个问题都是由同一件事引起的:Python通过引用而不是通过值传递列表
首先,简而言之,这意味着什么:
当用a
作为int调用foo(a)
时,在foo()
内部,只得到a
的值,而不是它在内存中的实际位置。你的论文上写了a
,你展示了foo()
,“这是a
,把它写下来。”
但是,当您使用b
作为列表或对象调用bar(b)
时,您不会得到b
的值,而是得到b
本身,即内存位置。你的论文上仍然有b
,但是你对bar()
,“嘿,b
非常复杂,可能不值得复制到一张新的纸上。你可以分享我的论文。”这对于防止你的程序变得非常慢很好,但是——正如你所经历的那样——这意味着任何更改bar()
make tob
changeb
无处不在
要解决问题,应该传递不希望更改的对象的副本。在将访问的添加到路由dict
时,您已经了解到了这一点,但实际上您应该这样做
find_all_routes(graph[i], graph, willing_to_travel - cur_node[i], visited[:], routesdict)
这意味着每次调用find_all_routes()
都会得到自己的已访问的个人副本
非常感谢!非常清楚的回答。我只是无法完全理解它。当我只需要按三下键的时候,我花了好几个小时试图让它工作,这有点令人沮丧,但嘿,这就是生活!完全地这就是为什么对于任何打算从事编程职业的人来说,在某个时候使用低级语言都是一个好主意。你开始看到很多以前没有看到的东西。非常感谢!非常清楚的回答。我只是无法完全理解它。当我只需要按三下键的时候,我花了好几个小时试图让它工作,这有点令人沮丧,但嘿,这就是生活!完全地这就是为什么对于任何打算从事编程职业的人来说,在某个时候使用低级语言都是一个好主意。你开始看到很多以前没有看到的东西。