寻找最短路径
BFS
BFS 只是访问 node,但是不会构造路径
frontier = Queue()
frontier.put(start )
reached = set()
reached.add(start)
while not frontier.empty():
current = frontier.get()
for next in graph.neighbors(current):
if next not in reached:
frontier.put(next)
reached.add(next)
路径
这时候把用于记录重复的数组,变为 parent 或者叫 come_form 记录父节点,或者叫从哪来的。就记录的路径
frontier = Queue()
frontier.put(start)
came_from = dict() # path A->B is stored as came_from[B] == A
came_from[start] = None // this!
while not frontier.empty():
current = frontier.get()
for next in graph.neighbors(current):
if next not in came_from:
frontier.put(next)
came_from[next] = current // this!
此时就能反推,从 goal 开始访问 come_from 就能得到最短路径
current = goal
path = []
while current != start
path.append(current)
current = came_from[current]
path.append(start) # optional
path.reverse() # optional
提前退出
发现到 goal 就直接退出,BFS 不需要访问所有路径
权重
不同路径会花费不同时间,算上权重,结果会和单纯的 BFS 不一样。
储存用的数据结构,也增到了三个。遍历用的、路径用的、权重用的
-
首先加权重要改变记录图的结构,从数组变为优先队列。优先队列先得到最小值
-
其次需要新增数据结构记录从开始到此节点的路径花费的权重,从路径最短转为权重最小
-
每次遍历时,需要计算当前权重。如果此节点没有访问过,或者小于之前访问此节点时的权重,才访问此节点
Dijkstra’s Algorithm (or Uniform Cost Search) :
搜索预测,贪婪 BFS
在 BFS 和 Dijkstra’s 中,都搜索了一层中所有节点,其实并不需要,只是想接近目标。
这时就需要让更接近目标的方向,有更多的权重,所以需要改变计算权重的方式
定义一个计算目标距离的函数
Dijkstra’s 使用真是距离,现在替换为定义的函数,并且不需要记录每个节点距离目标的权重
A*
Dijkstra’s 可以找到最短路径,但是会去搜索没有希望的路径,不会预测
贪婪 BFS,只去寻找最有希望的方向,但不一定会找到最短路径
这时候就需要他俩相结合,就得到了 A*
代码和 Dijkstra’s 很像,只是在其基础上,另外增加了权重