A_Star算法的C++实现(一)

A_Star算法代码初始版:

运行环境:vs2022

cpp 复制代码
#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
using namespace std;

struct Point
{
    int x, y;
    Point(int x, int y) :x(x), y(y) {}
    double distance(Point& p) {
        return sqrt((x - p.x) ^ 2 + (y - p.y) ^ 2);
    }
};

//定义节点
struct Node
{
    Point point;
    double g, h, f;
    Node* parent;
    Node(Point point, double g, double h, Node* parent = nullptr) :point(point), g(g),  h(h),f(g+h), parent(parent) {}
};


//自定义Node*的排序规则
struct NodeCompare {
    bool operator()(Node* n1, Node* n2){
        return (n1->f) < (n2->f);//升序排列
    }
};


//A-star
vector<Point>AstarPathPlanning(vector<vector<int>>& gridmap,Point &start,Point&goal) {
    int row = gridmap.size();//地图行,表示地图的宽
    int col = gridmap[0].size();//地图列,表示地图的长
    //定义openlist和closelist
    vector<Node*> openlist;//表示待搜索的节点
    vector<Node*> closelist;//表示已搜索的节点
    openlist.push_back(new Node(start,start.distance(start),start.distance(goal)));
    int count1 = 1;//统计new的次数
    vector<Point> path;
    while (!openlist.empty()) {
    //获取当前搜索节点current,即openlist中f最小的节点
        sort(openlist.begin(), openlist.end(),NodeCompare{});//先对openlist排序,这里要自定义排序规则
        Node* current = *openlist.begin();//openlist.begin()在排序后记为f最小的元素的迭代器位置
        openlist.erase(openlist.begin());//将current对应的元素从openlist中剔除
        closelist.push_back(current);//将current加入到closelist中
        //对当前搜索节点current进行分类讨论
        //1.current是重点,则返回路径,表示找到路径
        if (current->point.x == goal.x && current->point.y == goal.y)
        {
            while (current != nullptr)//利用父节点,从终点向起点回溯最短路径
            {
                path.push_back(current->point);
                current = current->parent;
            }
            reverse(path.begin(), path.end());//路径是反的,反转路径
            //仍然存在一定的问题,需要解决,因为openlist和closelist存储的元素都是new动态分配的内存,需要delete,否则会造成内存的泄露
            int count2 = 0;
            for (auto o : openlist) {
                delete o;
                count2++;
            }
            for (auto c : closelist)
            {
                delete c;
                count2++;
            }
            cout << "new的次数:" << count1 << endl;
            cout << "delete的次数:" << count2 << endl;
            return path;
        }
        //2.current不是重点,需要讨论其邻近的节点。
        int x = current->point.x;
        int y = current->point.y;
        vector<Point> neighbors = {//由current得到8个邻近点的坐标
            {x - 1,y - 1} ,{ x - 1,y } ,{ x - 1,y + 1 },
            { x,y - 1 }, { x,y + 1 },
            { x + 1,y - 1 } ,{ x + 1,y }, { x + 1,y + 1 }
        };
            //遍历所有邻近节点,每一个临近节点必须满足在地图内同时不是障碍物
        for (auto n : neighbors) {
            if ((n.x >= 0 && n.x < row) && (n.y >= 0 && n.y < col) && gridmap[n.x][n.y] == 0) {
            //2.1n在closelist中,表示已经探索过了,此时直接跳过
                bool incloselist = false;
                for (auto c : closelist) {
                    if (c->point.x == n.x && c->point.y == n.y) {
                        incloselist = true;
                        break;//此处的break是指,已经确认了外面for循环的n点是属于closelist中的,所以就没必要继续该遍历了,直接跳出该循环
                    }
                }
                if (incloselist) {
                    continue;//如果incloselist为true,则说明该点在closelist里面,则执行该if里面的continue语句,意味着结束该次外循环,也就是对该n点不进行操作,直接开始查找下一个n点的情况。
                }
                //2.2n是否在openlist中进行讨论
                bool inopenlist = false;
                for (auto o : openlist)
                {
                    if (o->point.x == n.x && o->point.y == n.y)
                    {
                        inopenlist = true;//如果在openlist当中,则对比值,更新代价值和父节点parent
                        double g = current->g + n.distance(current->point);//邻近节点n到起点的距离=当前搜索节点current到起点的距离+当前搜索节点current到邻近节点n的距离
                        double h = n.distance(goal);//邻近节点n到重点的估计距离代价
                        double f = g + h;
                        if (f < (o->f)) {
                            o->f = f;
                            o->parent = current;
                        }
                        break;//结束该循环,因为已经找到openlist中某一点就是当前neighbor中的该点,再继续循环已经没有意义了
                    }
                }
                if (!inopenlist) {//2.2.2 n不在openlist中,对比f值,计算代价值,添加到openlist中,下次备选
                    double g = current->g + n.distance(current->point);//邻近节点n到起点的距离=当前搜索节点current到起点的距离+当前搜索节点current到邻近节点n的距离
                    double h = n.distance(goal);//邻近节点n到重点的估计距离代价
                    double f = g + h;
                    openlist.push_back(new Node(n, g, h, current));
                    count1++;
                }
            }; 
        }
    }
    //搜索完成没有路径,表示路径规划失败,此时返回空路径
    int count2 = 0;
    for (auto o : openlist) {
        delete o;
        count2++;
    }
    for (auto c : closelist)
    {
        delete c;
        count2++;
    }
    cout << "new的次数:" << count1 << endl;
    cout << "delete的次数:" << count2 << endl;
    return path;
}


int main()
{
    vector<vector<int>> gridmap = {
        {0,0,1,0,0},
        {0,1,0,0,0},
        {0,0,0,1,0},
        {0,0,0,0,1},
        {1,0,0,0,0},
    };
    Point start(0, 0);
    Point goal(4, 4);

    //vector<vector<int>> gridmap{
    //{0,0,1,1,0,1,0,0},
    //{0,0,0,1,0,1,0,0},
    //{0,0,1,0,0,1,0,0},
    //{0,0,1,0,0,1,0,0},
    //{0,0,1,1,0,0,1,1},
    //{0,0,0,1,0,0,0,0},
    //{0,0,0,1,1,0,0,0},
    //};
    //Point start(0, 0);
    //Point goal(5, 4);

    vector<Point> path = AstarPathPlanning(gridmap, start, goal);
    cout << "最终的路径点数" << path.size() << endl;
    for (auto p : path)
    {
        if (p.x == goal.x && p.y == goal.y)
        {
            cout << "(" << p.x << "," << p.y << ")" << endl ;
        }
        else {
            cout << "(" << p.x << "," << p.y << ")"<<"->";
        }
    }
    return 0;
}
相关推荐
jiao0000118 分钟前
数据结构——队列
c语言·数据结构·算法
kaneki_lh22 分钟前
数据结构 - 栈
数据结构
铁匠匠匠22 分钟前
从零开始学数据结构系列之第六章《排序简介》
c语言·数据结构·经验分享·笔记·学习·开源·课程设计
C-SDN花园GGbond24 分钟前
【探索数据结构与算法】插入排序:原理、实现与分析(图文详解)
c语言·开发语言·数据结构·排序算法
迷迭所归处1 小时前
C++ —— 关于vector
开发语言·c++·算法
leon6252 小时前
优化算法(一)—遗传算法(Genetic Algorithm)附MATLAB程序
开发语言·算法·matlab
CV工程师小林2 小时前
【算法】BFS 系列之边权为 1 的最短路问题
数据结构·c++·算法·leetcode·宽度优先
Navigator_Z2 小时前
数据结构C //线性表(链表)ADT结构及相关函数
c语言·数据结构·算法·链表
还听珊瑚海吗2 小时前
数据结构—栈和队列
数据结构
Aic山鱼2 小时前
【如何高效学习数据结构:构建编程的坚实基石】
数据结构·学习·算法