寻路算法分类与适用场景详解,寻路算法与路径规划算法纵览:从BFS、A*到D与RRT
前言
之前已经介绍了两种常用的寻路算法BFS和A*,本章将介绍并总结一下现有寻路算法的特点和优缺点。
除了广为人知的 BFS 和 A*,还有很多其他算法,它们各有优劣,适用于不同的场景。
寻路算法分类
我们把这些算法分为四大类来介绍
- 基于图搜索的算法(BFS/DFS/Dijkstra等)
BFS算法具体实现代码参考:《基于JavaScript实现BFS(广度优先搜索)路径搜索算法代码,并通过动画动态展现BFS 的搜索过程》 - 启发式算法(比如A和各种变种)
A算法具体实现代码参考:《基于JavaScript实现A寻路算法代码,并通过动画动态展现A寻路的过程》 - 适用于连续空间的算法(快速随机探索树(RRT)、概率路图(PRM))
- 仿生学算法(遗传算法和蚁群算法)
下面是详细介绍:
1. 基于图搜索的算法(BFS/DFS/Dijkstra 的“近亲”)
这类算法通常用于离散的图结构(如网格)。
-
Dijkstra 算法
- 核心思想:找到图中从起点到所有节点的最短路径。它是贪心算法,总是优先扩展当前代价最小的节点。
- 与 BFS/A* 的区别:
- 与 BFS 相比,BFS 假设所有边的代价相同(即步数),而 Dijkstra 可以处理不同代价的边(例如,平地代价为1,沼泽代价为5)。
- 与 A* 相比,Dijkstra 没有启发式函数,它会“盲目地”向所有方向扩展,直到找到目标。因此通常比 A* 慢。
- 适用场景:当需要知道到图中所有点的最短路径,或者图中没有合适的启发式函数时。
-
最佳优先搜索
- 核心思想:与 Dijkstra 类似,但它使用启发式函数
h(n)(到目标的估计距离)作为优先级,而不是从起点到该节点的实际代价g(n)。它试图尽可能地靠近目标。 - 与 A 的区别*:A* 结合了
g(n)(实际代价)和h(n)(估计代价)。而最佳优先搜索只关心h(n)。 - 优缺点:它通常比 Dijkstra 更快,但不保证找到最短路径,可能会被误导进入死胡同。
- 核心思想:与 Dijkstra 类似,但它使用启发式函数
2. A* 算法的变种与优化
A* 本身非常强大,但人们为了应对不同需求,发展出了许多变种。
-
迭代加深 A(IDA)**
- 核心思想:结合了 A* 和迭代加深 DFS 的思想。它不再维护一个开放的优先级队列,而是进行一系列深度优先搜索,每次搜索的代价阈值
f(n)递增。 - 优点:内存占用极低,因为它本质是深度优先搜索。适用于内存受限的环境。
- 缺点:对于某些图结构,可能会重复访问大量节点,导致时间变慢。
- 核心思想:结合了 A* 和迭代加深 DFS 的思想。它不再维护一个开放的优先级队列,而是进行一系列深度优先搜索,每次搜索的代价阈值
-
Weighted A(加权 A)**
- 核心思想:在 A* 的评估函数
f(n) = g(n) + w * h(n)中,给启发式函数h(n)加上一个权重w(w > 1)。 - 效果:这会让算法更“贪婪”,更倾向于向目标前进,从而更快地找到一条路径,但这条路径可能不是最优的,而是次优的。这是一种典型的用最优性换取速度的权衡。
- 核心思想:在 A* 的评估函数
-
D(D-Star,动态 A)**
- 核心思想:专注于动态环境的寻路。它首先从目标点开始向起点搜索,得到一个路径。当环境发生变化(如出现新障碍)时,它能高效地修复现有路径,而不需要像 A* 那样完全重新规划。
- 适用场景:机器人导航、实时战略游戏,其中地图信息会随时改变。
-
LPA(终身规划 A)**
- 核心思想:D* 的推广和优化。同样用于动态环境,它结合了 A* 和增量搜索的思想,能够利用上一次的搜索结果来更高效地应对地图变化。
-
Theta*
- 核心思想:对 A* 找到的路径进行后处理优化,允许路径在网格点之间“任意角度”移动,而不仅仅局限于网格线。最终生成的路径比标准的 A* 网格路径更短、更平滑。
- 适用场景:任何基于网格的系统,希望得到更自然的路径,如无人机飞行、RTS 游戏。
3. 适用于连续空间的算法
这类算法用于机器人、动画等需要在二维或三维连续空间中规划路径的场景。
-
快速随机探索树(RRT)
- 核心思想:通过在空间中随机采样,并尝试将采样点与已有的树连接起来,从而快速构建一棵覆盖整个空间的探索树。它不追求最优路径,而是追求快速找到一条可行路径。
- 优点:在高维连续空间中非常高效,能快速探索复杂环境。
- 缺点:路径通常不是最优的,甚至可能很绕。
- 变种:RRT*(渐近最优的RRT)通过“重连”优化,能使找到的路径逐渐逼近最优。
-
概率路图(PRM)
- 核心思想:分为两个阶段:
- 学习阶段:在空间中随机撒点(“里程碑”),并将它们连接成一个图。
- 查询阶段:在这个构建好的路图上使用 A* 或 Dijkstra 等算法来寻找路径。
- 适用场景:当需要进行多次路径查询的静态环境,构建一次路图可以反复使用。
- 核心思想:分为两个阶段:
4. 仿生学算法
这类算法受自然现象启发,适用于非常复杂、非凸的优化问题。
-
遗传算法
- 核心思想:模拟自然选择。将路径编码为“基因”,通过选择、交叉(杂交)、变异等操作,让路径种群不断“进化”,最终收敛到一个较好的解。
- 适用场景:传统搜索方法难以解决的复杂路径规划问题。
-
蚁群算法
- 核心思想:模拟蚂蚁觅食。虚拟的“蚂蚁”在探索时会留下“信息素”,其他蚂蚁更倾向于走信息素浓的路径。好的路径会被强化,差的路径会逐渐消失。
- 适用场景:组合优化问题,如旅行商问题,也可以用于路径规划。
总结与选择
| 算法名称 | 核心特点 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|---|
| BFS | 层层扩展,代价相同 | 保证最短路径(步数),简单 | 慢,内存占用大 | 简单网格,找最短步数 |
| Dijkstra | 扩展到最小代价节点 | 保证最短路径(不同代价) | 比 A* 慢,无方向性 | 需要到所有点的路径,或无启发式函数 |
| A* | f(n) = g(n) + h(n) | 高效、最优,最常用 | 启发函数设计影响大 | 绝大多数静态环境寻路 |
| IDA* | 迭代加深的 A* | 内存占用极低 | 可能重复访问节点 | 内存受限的系统 |
| D/LPA** | 动态重规划 | 高效处理地图变化 | 实现复杂 | 机器人、动态环境游戏 |
| RRT | 随机采样建树 | 在高维空间快,易实现 | 路径不最优 | 机器人臂、无人机运动规划 |
| 遗传算法 | 模拟自然进化 | 能解复杂问题 | 参数敏感,可能不收敛 | 超复杂路径优化 |
简单选择指南:
- 绝大多数游戏和通用寻路:A* 是你的首选。
- 地图会动态变化(如障碍物移动):考虑 D* 或 LPA*。
- 内存非常紧张:试试 IDA*。
- 不需要绝对最优,但要非常快:Weighted A* 或 RRT。
- 机器人、连续空间运动:RRT 或 PRM。
- 问题极其复杂,传统方法失效:可以尝试 遗传算法 或 蚁群算法。
