A*算法是一种在图形平面上,有多个节点的路径中,寻找一条从起始点(source)到目标点(goal)的最短遍历路径的算法。它属于启发式搜索算法,因为它使用启发式方法来计算图中的节点,从而减少实际计算的节点数量。
A*(A星)算法是一种启发式搜索算法,用于在图中找到从起始点(source)到目标点(goal)的最短路径。它属于最佳优先搜索算法的一种,使用启发式方法来估计从当前节点到目标节点的距离,以此来优化搜索过程。
算法原理
A*算法的核心思想是,它在搜索过程中,对每个节点计算两个值:
1. g(n):从起始点到当前节点n的实际代价。
2. h(n):从当前节点n到目标点的估计代价(启发式函数)。
算法使用这两个值的和(f(n) = g(n) + h(n))来评估每个节点的优先级。节点的f(n)值越小,被优先搜索的可能性越大。
启发式函数(Heuristic Function)
启发式函数h(n)是A*算法的关键部分,它必须满足以下条件:
- 一致性(或称为单调性):对于任意节点n,h(n)的值不能超过从n到目标点的实际最小代价。一致性保证了算法的最优性。
- 可接受性:h(n)的值不能为负。
常见的启发式函数包括:
- 曼哈顿距离:在网格地图中,当只能沿着水平或垂直方向移动时,从一点到另一点的最短路径长度。
- 欧几里得距离:直线距离,即两点之间的直线最短距离。
- 切比雪夫距离:在网格地图中,从一个点到另一个点的最短路径,允许对角线移动。
算法步骤
1. 初始化:将起始点加入开放列表(Open List),并设置其g(n)和h(n)值为0。
2. 循环:当开放列表非空时,执行以下步骤:
- 从开放列表中取出f(n)值最小的节点n。
- 如果n是目标点,则路径已经找到,可以停止搜索。
- 否则,将n从开放列表移至关闭列表(Closed List),并遍历n的所有邻居节点:
- 如果邻居节点已经在关闭列表中,忽略它。
- 如果邻居节点不在开放列表中,将其添加到开放列表,并计算它的g(n)和h(n)值。
- 如果邻居节点已在开放列表中,检查通过n到达该邻居节点是否更优(即g(n)值更小),如果是,则更新它的g(n)值和父节点。
3. 结束:如果开放列表为空,表示无法到达目标点。
特点
- 性能:A*算法的性能取决于启发式函数的选择。好的启发式函数可以显著减少搜索空间,提高效率。
- 最优性:如果启发式函数是一致的,A*算法可以保证找到最短路径。
- 适用性:A*算法适用于各种类型的图搜索问题,包括路径规划、游戏AI、机器人导航等领域。
A*算法是一种非常强大且灵活的算法,通过调整启发式函数,可以适应不同的应用场景。
以下是A*算法的一个基本的C/C++实现示例。这个示例不包括特定的数据结构,如优先队列,你可能需要根据你的具体需求来实现或使用现有的库。
#include <iostream>
#include <vector>
#include <queue>
#include <unordered_map>
#include <cmath>
#include <algorithm>
// 定义点的结构
struct Point {
int x, y;
};
// 定义优先队列中的元素,包含点、成本、启发式估计和父节点
struct Node {
Point pt;
double cost;
double heuristic;
Node* parent;
Node(Point pt, double cost, double heuristic, Node* parent) :
pt(pt), cost(cost), heuristic(heuristic), parent(parent) {}
// 优先队列需要比较操作,这里定义一个比较函数
bool operator>(const Node& other) const {
return cost + heuristic > other.cost + other.heuristic;
}
};
// 定义优先队列
typedef std::priority_queue<Node, std::vector<Node>, std::greater<Node>> PriorityQueue;
// 定义启发式函数,这里使用曼哈顿距离
double heuristic(const Point& a, const Point& b) {
return std::abs(a.x - b.x) + std::abs(a.y - b.y);
}
// A*算法实现
std::vector<Point> aStarSearch(Point start, Point end, std::unordered_map<Point, std::vector<Point>> graph) {
PriorityQueue pq;
std::unordered_map<Point, double> costSoFar;
std::unordered_map<Point, bool> visited;
pq.push(Node(start, 0.0, heuristic(start, end), nullptr));
costSoFar[start] = 0;
visited[start] = false;
while (!pq.empty()) {
Node current = pq.top();
pq.pop();
if (current.pt == end) {
// 找到终点,回溯路径
std::vector<Point> path;
while (current.parent) {
path.push_back(current.pt);
current = *current.parent;
}
std::reverse(path.begin(), path.end());
return path;
}
if (visited[current.pt]) continue;
visited[current.pt] = true;
for (Point neighbor : graph[current.pt]) {
if (visited[neighbor]) continue;
double newCost = current.cost + 1; // 假设每步成本为1
double heuristicCost = heuristic(neighbor, end);
if (costSoFar.find(neighbor) == costSoFar.end() || newCost < costSoFar[neighbor]) {
costSoFar[neighbor] = newCost;
pq.push(Node(neighbor, newCost, heuristicCost, new current));
}
}
}
return std::vector<Point>(); // 没有找到路径
}
int main() {
Point start = {0, 0};
Point end = {10, 10};
// 构建图,这里简单使用二维网格的四个邻居
std::unordered_map<Point, std::vector<Point>> graph;
for (int x = 0; x <= 10; ++x) {
for (int y = 0; y <= 10; ++y) {
Point pt = {x, y};
graph[pt] = { {x-1, y}, {x+1, y}, {x, y-1}, {x, y+1} };
}
}
std::vector<Point> path = aStarSearch(start, end, graph);
for (const Point& pt : path) {
std::cout << "(" << pt.x << ", " << pt.y << ")" << std::endl;
}
return 0;
}
这个代码示例提供了A*算法的基本框架,包括启发式函数、优先队列和搜索逻辑。你需要根据你的具体应用场景来调整图的表示和启发式函数。此外,你可能还需要考虑如何处理障碍物和不同的移动成本。
标签:std,Point,实现,C++,current,算法,启发式,节点 From: https://blog.csdn.net/2401_86771711/article/details/141465194