问题描述
graph = {}
graph['you'] = ['alice','bob','claire']
graph['bob'] = ['anuj','peggy']
graph['alice'] = ['peggy']
graph['claire'] = ['thom','jonny']
graph['anuj'] = []
graph['peggy'] = []
graph['thom'] = []
graph['jonny'] = []
确定我的终端节点的函数:
def person_is_seller(name):
return name[-1] == 'm' # thom is the mango seller
广度优先搜索算法:
from collections import deque
def search(name):
search_queue = deque()
search_queue += graph[name]
searched = set()
while search_queue:
# print(search_queue)
person = search_queue.popleft()
if person not in searched:
# print(f'Searching {person}')
if person_is_seller(person):
return f'{person} is a mango seller'
else:
search_queue += graph[person]
searched.add(person)
return f'None is a mango seller'
search('you')
# 'thom is a mango seller'
我想知道这个算法是否可以返回从you
到thom
的最短路径?
[you,claire,thom] # as this is the shortest path to thom which is my end node
我检查了 this answer,它指出它不会让我找到最短路径,但第二个答案指出可以提供最短路径,我假设不使用 Djikstra's algorithm。所以我有点困惑,我可以以某种方式跟踪前一个节点,如果到达最后一个节点,请提供最后一个代码片段或任何其他格式中的最短路径?
解决方法
您可以将 searched
设为字典而不是集合,然后让每个键的值作为对您来自的节点的反向引用。
当您找到目标时,您可以通过返回这些反向引用来恢复路径,然后返回反向引用。
修改后的代码:
def search(name):
search_queue = deque()
search_queue.append((name,None))
searched = {} # dict instead of set
while search_queue:
# print(search_queue)
person,prev = search_queue.popleft()
if person not in searched:
searched[person] = prev
# print(f'Searching {person}')
if person_is_seller(person):
result = []
while person is not None:
result.append(person)
person = searched[person]
return result[::-1]
else:
search_queue += [(neighbor,person) for neighbor in graph[person]]
return []
现在函数返回一个列表。当找到路径时,它将具有开始和结束节点,因此在这种情况下:
['you','claire','thom']
如果没有找到路径,结果是一个空列表。
,如果每条边的长度相同,您可以使用 BFS 找到最短路径。当不同的边具有不同的权重时,Dykstra 算法是必要的。
纯形式的 Dykstra 算法仅计算最短路径的长度。由于您可能需要最短路径本身,因此您需要将每个访问过的节点与边缘另一端的节点相关联,这通常使用关联数组(Python 中的“字典”)完成。