A*算法通过f(n)=g(n)+h(n)评估函数结合Dijkstra与启发式搜索,使用优先队列管理Open List、集合标记Closed List,按曼哈顿或欧几里得距离设计h(n),在网格中寻优路径。

实现A*(A星)搜索算法的关键在于结合Dijkstra最短路径思想与启发式估计函数。它通过评估函数 f(n) = g(n) + h(n) 来选择最优扩展节点,其中 g(n) 是从起点到当前节点的实际代价,h(n) 是从当前节点到目标的启发式估计代价。
1. 定义节点结构
每个搜索节点需要记录位置、代价信息以及用于重建路径的父节点。
Struct node {
int x, y;
double g, f;
Node* parent;
// 构造函数
Node(int x, int y, double g = 0, double f = 0, Node* p = nullptr)
: x(x), y(y), g(g), f(f), parent(p) {}
// 优先队列比较:按f值从小到大排序
bool operator>(const Node& other) const {
return f > other.f;
}
};
2. 启发式函数设计
常用曼哈顿距离或欧几里得距离作为 h(n),根据地图类型选择。
double heuristic(int x1, int y1, int x2, int y2) {
// 曼哈顿距离(适用于4方向移动)
return abs(x1 – x2) + abs(y1 – y2);
}
// 若允许8方向可改用对角线距离或欧氏距离
3. 维护Open和Closed列表
使用优先队列管理待扩展节点(Open List),用集合或二维数组标记已访问节点(Closed List)。
立即学习“C++免费学习笔记(深入)”;
priority_queue
bool closed[ROWS][COLS] = {false};
// 或使用set
air
4. 主循环逻辑
从起点开始,不断取出f最小节点,生成邻居并更新代价,直到到达目标。
while (!openList.empty()) {
Node current = openList.top(); openList.pop();
if (current.x == goalX && current.y == goalY) {
// 找到路径,回溯构建结果
break;
}
closed[current.x][current.y] = true;
// 遍历上下左右四个方向(或八个)
for (each neighbor dx, dy) {
int nx = current.x + dx, ny = current.y + dy;
if (nx = ROWS || ny = COLS) continue;
if (grid[nx][ny] == OBSTACLE || closed[nx][ny]) continue;
double tentative_g = current.g + 1; // 假设单位步长
// 如果该邻居未被探索或找到更短路径
if (!inOpenList(nx, ny) || tentative_g gScore[nx][ny] = tentative_g;
double f_score = tentative_g + heuristic(nx, ny, goalX, goalY);
openList.push(Node(nx, ny, tentative_g, f_score, ¤t));
}
}
}
注意:实际中需维护 gScore 数组,并考虑指针有效性(建议用智能指针或索引代替裸指针)。
5. 路径重建
当目标节点被处理后,通过 parent 指针逆向追踪路径。
vector
Node* p = &goalNode;
while (p != nullptr) {
path.push_back({p->x, p->y});
p = p->parent;
}
reverse(path.begin(), path.end());
基本上就这些。核心是合理组织数据结构、正确计算估价函数,并保证开放列表有序性。A*在网格寻路、游戏AI中有广泛应用,效率依赖于启发函数的质量。


