我正在尝试使用 Dijkstra 算法编写最短路径查找器,但它似乎不起作用。我不知道问题出在哪里。我正在研究 Python 3.5 并关注 此视频。
这是代码:
graph = {
'A': {'B': 10, 'D': 4, 'F': 10},
'B': {'E': 5, 'J': 10, 'I': 17},
'C': {'A': 4, 'D': 10, 'E': 16},
'D': {'F': 12, 'G': 21},
'E': {'G': 4},
'F': {'E': 3},
'G': {'J': 3},
'H': {'G': 3, 'J': 3},
'I': {},
'J': {'I': 8},
}
def dijkstra(graph, start, end):
D = {}
P = {}
for node in graph.keys():
D[node]= -1
P[node]=""
D[start]=0
unseen_nodes=graph.keys()
while len(unseen_nodes) > 0:
shortest=None
node=' '
for temp_node in unseen_nodes:
if shortest==None:
shortest = D[temp_node]
node = temp_node
elif D[temp_node]<shortest:
shortest=D[temp_node]
node=temp_node
unseen_nodes.remove(node)
for child_node, child_value in graph[node].items():
if D[child_node] < D[node] + child_value:
D[child_node] = D[node] + child_value
P[child_node]=node
path = []
node = end
while not (node==start):
if path.count(node)==0:
path.insert(0, node)
node=P[node]
else:
break
path.insert(0, start)
return path
这是错误消息:
AttributeError: 'dict_keys' object has no attribute 'remove'
dict.keys()
返回一个dict_keys对象(字典的视图),它没有remove
方法;与 Python 2 不同,其中 dict.keys()
返回一个列表对象。
>>> graph = {'a': []}
>>> keys = graph.keys()
>>> keys
dict_keys(['a'])
>>> keys.remove('a')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'dict_keys' object has no attribute 'remove'
您可以使用
list(..)
获取按键列表:
>>> keys = list(graph)
>>> keys
['a']
>>> keys.remove('a')
>>> keys
[]
unseen_nodes = graph.keys()
到
unseen_nodes = list(graph)
在 Python 2 中,
graph.keys()
返回一个定义 remove()
方法的列表(请参阅此处的演示)。 graph.keys()
是一个列表也意味着它是 graph
的键在当前状态下的新副本)。在 Python 3 中,它返回一个 dict_keys 对象,它是字典键的视图(这意味着每当修改 graph
时,视图也会更改)。
由于 OP 想要创建定义
remove()
方法的字典键的新副本,因此另一种方法是创建 set
。换句话说,改变
unseen_nodes = graph.keys()
到
unseen_nodes = set(graph)
然后可以使用
remove
方法删除节点。一个示例的工作原理如下。
graph = {'a': 2, 'b': 1}
unseen_nodes = set(graph)
unseen_nodes.remove('a') # remove node `a`
unseen_nodes # the remaining nodes: {'b'}
集合相对于列表的一个优点是它更快。例如,从集合中删除项目比从列表中删除项目要快得多。下面的测试表明,从集合中删除项目比从列表中删除项目快 1000 倍以上。
from timeit import timeit
setup = '''
import random
lst = list(range(100000))
st = set(range(100000))
keys = iter(random.sample(range(100000), 100000))
'''
t1 = timeit('lst.remove(next(keys))', setup, number=100000)
t2 = timeit('st.remove(next(keys))', setup, number=100000)
print(t1/t2) # 1330.4911104284974