基于C++实现的A*算法(链表和二叉堆实现)

基于C++实现的A*算法

  • AStar算法相对于Dijkstra算法而言升级的地方在于引入了启发距离,即H(当前点到终点的预计距离),因此在每次大循环中Dijkstra算法找的最短距离仅仅是G(起点到当前点的距离),而AStar算法找的是(G+H)即F的最小值,因此AStar算法可以更快的找到终点,从而在判断两点最短路径时候有着更快的结束时间即更高的效率

  • 这两种算法本质上而言均是找起点到每一个点的最短距离,而AStar算法好就好在它引入了每次对终点的度量因而可以比Dijkstra算法更快的找到对终点的距离!

    其具体的原理步骤可以参见其他优秀的blog如:A* 寻路算法 - christanxw的专栏 - C++博客

基于c++的链表的A*算法代码如下:

AStar.h文件

#pragma once
#include<vector>
#include<list>
#include<memory>
#include<algorithm>
#include<iostream>
struct ANode
{
    ANode(int X, int Y, std::shared_ptr<ANode> p = nullptr) : x(X), y(Y), prev(p) {}
    int x; //点的x坐标
    int y; //点的y坐标
    int G=0; //起点到该点的欧拉距离
    int H=0;//该点到终点的曼哈顿距离
    int F=0;//G+H
    std::weak_ptr<ANode> prev;//指向的前一个节点!!!改成了weak_ptr不然数据多的时候析构报错
 
};
class AStar
{
public:
    AStar(std::vector<std::vector<int>> m ): maps(m) {}
    std::shared_ptr<ANode> findPath(std::shared_ptr<ANode> beg, std::shared_ptr<ANode> end);
    void PrintAStarPath(const std::pair<int, int> &, const std::pair<int, int> &);
    ~AStar()
    {
        openlist.clear();
        closeist.clear();
    }
private:
    void refreshOpenList(std::shared_ptr<ANode>, std::shared_ptr<ANode> end);
    int calculateH(std::shared_ptr<ANode>, std::shared_ptr<ANode>) const;
    int calculateF(std::shared_ptr<ANode>,std::shared_ptr<ANode>) const;

private:
    std::vector<std::vector<int>> maps;//地图
    std::list<std::shared_ptr<ANode>> openlist;//保存还未遍历过的节点
    std::list<std::shared_ptr<ANode>> closeist;//保存已经找到最短路径的节点
    const static int costLow;//上下位移的距离
    const static int costHigh;//斜向位移的距离
};
const int AStar::costLow = 10;
const int AStar::costHigh = 14;
int AStar::calculateH(std::shared_ptr<ANode> point, std::shared_ptr<ANode> end) const
{
    return costLow * (std::abs(point->x - end->x) + std::abs(point->y - end->y));
}
int AStar::calculateF(std::shared_ptr<ANode> point,std::shared_ptr<ANode> end) const
{
    return point->G + calculateH(point, end);
}
std::shared_ptr<ANode> AStar::findPath(std::shared_ptr<ANode> beg, std::shared_ptr<ANode> end)
{
    refreshOpenList(beg,end);
    while (!openlist.empty())
    {
        auto iter = std::min_element(openlist.cbegin(), openlist.cend(), [](std::shared_ptr<ANode> p1, std::shared_ptr<ANode> p2)
                                     { return p1->F <= p2->F;});
        closeist.push_back(*iter);
        std::shared_ptr<ANode> iter_temp = *iter;
        openlist.erase(iter);
        refreshOpenList(iter_temp, end);
        auto iter2 = std::find_if(openlist.cbegin(), openlist.cend(), [end](std::shared_ptr<ANode> sp)
                                  { return (sp->x == end->x) && (sp->y == end->y); });
        if (iter2 != openlist.end())
            return *iter2;
    }
    return nullptr;
}
void AStar::refreshOpenList(std::shared_ptr<ANode> point, std::shared_ptr<ANode> end)
{
    bool upIsWall = false;//表示当前点上有障碍物,即对应的斜向没法走
    bool downIsWall = false;
    bool leftIsWall = false;
    bool rightIsWall = false;
    if (point->x - 1 >= 0 && maps[point->x - 1][point->y] == 1)
        upIsWall = true;
    if (point->x + 1 < int(maps.size()) && maps[point->x + 1][point->y] == 1)
        downIsWall = true;
    if (point->y - 1 >= 0 && maps[point->x][po
  • 2
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值