商城首页欢迎来到中国正版软件门户

您的位置:首页 >C++实现A寻路算法详解

C++实现A寻路算法详解

  发布于2025-11-21 阅读(0)

扫一扫,手机访问

A*寻路算法通过f(n)=g(n)+h(n)评估节点,使用优先队列管理开放列表,结合曼哈顿距离启发函数与网格邻居扩展,最终找到从起点到终点的最优路径。

c++怎么实现A寻路算法_c++ A寻路算法实现方法

在C++中实现A*(A星)寻路算法,核心是结合Dijkstra最短路径思想与启发式搜索。它通过评估每个节点的f(n) = g(n) + h(n)来选择最优路径,其中g(n)是从起点到当前点的实际代价,h(n)是当前点到终点的预估代价(启发函数),通常使用曼哈顿距离或欧几里得距离。

1. 定义节点结构

每个网格点需要记录坐标、代价值以及父节点信息,用于回溯路径:

struct Node {
    int x, y;
    double g, h, f;
    Node* parent;
Node(int x, int y) : x(x), y(y), g(0), h(0), f(0), parent(nullptr) {}

bool operator==(const Node& other) const {
    return x == other.x && y == other.y;
}

};

2. 启发函数设计

常用曼哈顿距离作为h值,在四方向移动场景下更合适:

double heuristic(Node& a, Node& b) {
    return abs(a.x - b.x) + abs(a.y - b.y); // 曼哈顿距离
}

3. 开放列表和关闭列表管理

用优先队列维护开放列表(按f值排序),用set或vector管理已访问节点:

#include <queue>
#include <set>
#include <vector>

struct CompareNode { bool operator()(Node a, Node b) { return a->f > b->f; // 小顶堆 } };

std::priority_queue<Node, std::vector<Node>, CompareNode> openList; std::set<std::pair<int, int>> closedSet;

4. 主搜索循环实现

从起点开始扩展邻居,更新代价值并加入开放列表,直到找到终点:

std::vector<Node*> findPath(int grid[][COL], int rows, int cols, Node& start, Node& end) {
    openList.push(&start);
while (!openList.empty()) {
    Node* current = openList.top(); openList.pop();

    if (current-&gt;x == end.x &amp;&amp; current-&gt;y == end.y) {
        // 构建路径
        std::vector&lt;Node*&gt; path;
        while (current) {
            path.push_back(current);
            current = current-&gt;parent;
        }
        reverse(path.begin(), path.end());
        return path;
    }

    closedSet.insert({current-&gt;x, current-&gt;y});

    // 遍历上下左右四个方向
    int dx[] = {0, 0, -1, 1};
    int dy[] = {-1, 1, 0, 0};

    for (int i = 0; i &lt; 4; ++i) {
        int nx = current-&gt;x + dx[i];
        int ny = current-&gt;y + dy[i];

        if (nx &lt; 0 || nx &gt;= rows || ny &lt; 0 || ny &gt;= cols) continue;
        if (grid[nx][ny] == 1) continue; // 1表示障碍物
        if (closedSet.find({nx, ny}) != closedSet.end()) continue;

        Node* neighbor = new Node(nx, ny);
        double tentative_g = current-&gt;g + 1; // 假设每步代价为1

        bool isNew = true;
        for (auto&amp; n : openListContainer) { // 注意:priority_queue不支持遍历,需额外容器辅助
            if (*n == *neighbor) {
                isNew = false;
                if (tentative_g &lt; n-&gt;g) {
                    n-&gt;g = tentative_g;
                    n-&gt;f = n-&gt;g + n-&gt;h;
                    n-&gt;parent = current;
                }
                break;
            }
        }

        if (isNew) {
            neighbor-&gt;g = tentative_g;
            neighbor-&gt;h = heuristic(*neighbor, end);
            neighbor-&gt;f = neighbor-&gt;g + neighbor-&gt;h;
            neighbor-&gt;parent = current;
            openList.push(neighbor);
            openListContainer.push_back(neighbor); // 辅助查找
        }
    }
}
return {}; // 无路径

}

注意:标准priority_queue无法遍历,实际项目中可用multiset或自定义可更新堆结构优化性能。

5. 使用建议与优化

实际应用时注意以下几点:

  • 避免内存泄漏,路径生成后释放动态创建的Node对象
  • 可用二维数组预分配所有节点,减少new/delete开销
  • 对于大地图,考虑使用跳点搜索(Jump Point Search)加速
  • 若允许对角线移动,调整移动方向和距离计算方式

基本上就这些,A*算法逻辑清晰,关键是正确维护g、h、f值和节点状态。

本文转载于:互联网 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。

热门关注