← 返回题目列表

A* 搜索和 Dijkstra 有什么区别?启发函数为什么重要?

困难 第 30 / 30 题 更新于 2026/07/30
A星最短路径启发式搜索

简化版

A* 可以看成带启发函数的 Dijkstra。

Dijkstra 按当前已知距离 g(n) 扩展节点;A* 按 f(n) = g(n) + h(n) 扩展,其中 h(n) 是从当前节点到目标的估计距离。

如果启发函数不高估真实距离,A* 可以保证找到最短路径,并且通常比 Dijkstra 少扩展很多节点。

详细版

A* 常用于地图寻路。

符号含义
g(n)起点到当前节点的真实已知代价
h(n)当前节点到目标的估计代价
f(n)g(n) + h(n),优先队列排序依据

Dijkstra 可以看成 h(n) = 0 的 A*。

启发函数越接近真实距离,搜索越有方向;但如果高估真实代价,可能破坏最短路径保证。

完整版教学

1. Dijkstra 的扩展方式

Dijkstra 从起点开始,每次扩展当前 dist 最小的节点。

它不关心目标在哪,只是均匀地向外扩散。

在地图中,如果目标在右上角,Dijkstra 仍可能向左下方扩展很多无关节点。

这就是 A* 想优化的地方。

2. A* 的核心公式

A* 给每个节点一个估价:

f(n) = g(n) + h(n)

其中:

  • g(n) 是起点到 n 的已知代价;
  • h(n)n 到目标的估计代价;
  • f(n) 是经过 n 到目标的总估计代价。

A* 的本质是让最短路径搜索带上“朝目标走”的方向感。

3. 启发函数 h 为什么重要

如果 h 太小,比如一直为 0,A* 就退化成 Dijkstra。

如果 h 很接近真实距离,搜索会更集中。

如果 h 高估真实距离,算法可能过早放弃真正最短路径方向。

h 的性质影响
h = 0退化为 Dijkstra
不高估真实距离保证最优性
接近真实距离扩展节点更少
高估真实距离可能不保证最短

4. 什么叫可采纳启发函数

可采纳启发函数要求:

h(n) <= 从 n 到目标的真实最短距离

也就是不能高估。

例如在四方向网格中,如果每步代价为 1,曼哈顿距离通常是可采纳的:

abs(x1 - x2) + abs(y1 - y2)

因为你至少要走这么多水平和垂直步。

5. 常见启发函数怎么选

不同移动规则对应不同启发函数。

场景常见 h
四方向网格曼哈顿距离
八方向网格对角距离或欧几里得距离
地图导航直线距离
状态搜索问题特定下界

选择启发函数时,要保证它是目标距离的合理下界。

6. A* 的数据结构

A* 通常也用优先队列。

队列按 f(n) 排序:

openSet.push(node, priority = g[node] + h[node])

还需要记录:

  1. gScore:起点到节点的当前最好代价;
  2. cameFrom:用于恢复路径;
  3. closed 集合:已经处理过的节点。

7. 和 Dijkstra 怎么对比

可以这样说:

维度DijkstraA*
排序依据g(n)g(n) + h(n)
是否需要目标不强依赖依赖目标
搜索方向均匀扩散朝目标引导
最优性条件非负权边非负权边 + 合理 h

如果没有明确目标,A* 的启发意义不大;如果目标明确,A* 往往更高效。

8. 常见误区与追问

  • 误区:A 一定比 Dijkstra 快。* 如果启发函数很差,A* 可能接近 Dijkstra,甚至有额外开销。
  • 误区:启发函数越大越好。 高估真实距离可能破坏最短路径保证。
  • 误区:A 不需要优先队列。* 实现上通常仍然依赖优先队列按 f 取最小。
  • 追问:Dijkstra 是 A 的特例吗?* 可以看成 h(n)=0 的 A*。
  • 追问:曼哈顿距离什么时候适合? 适合四方向网格、每步代价一致的场景。