微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用广度优先搜索返回最短路径

如何解决使用广度优先搜索返回最短路径

我有一个graph

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'

我想知道这个算法是否可以返回从youthom的最短路径?

[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 中的“字典”)完成。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。