我正在编写一个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[:]
但是我对于没有访问列表打破我的递归更加无能为力!
答案 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
的个人副本。