赞
踩
目录
A*算法,A*(A-Star)算法是一种静态路网中求解最短路径最有效的直接搜索方法,也是解决许多搜索问题的有效算法。算法中的距离估算值与实际值越接近,最终搜索速度越快(百度百科)
百科百科将A*算法定义为求解最短路径,我认为不够严谨。
G 表示从起点移动到终点的移动距离H 表示从指定的地点移动到终点的预计移动距离F = G + H ,F 即表示从起点经过此点预计到终点的总移动距离
距离有两个指标:
曼哈顿距离:两个点在标准坐标系上的绝对轴距总和。计算公式:|x1-x2|+|y1-y2|
欧式距离:两个点的直线距离 。计算公式:
A*算法首先定义两个重要的链表:openList、closeList
通过循环将可能到达的结点加入openList,已经走过的结点加入closeList
1)动态展示
2)静态展示
1. 从起点开始, 把它作为待处理的方格存入一个预测可达的节点列表,简称 openList, 即把起点放入“预测可达节点列表”, 可达节点列表 openList 就是一个等待检查方格的列表。2. 寻找 openList 中 F 值最小的点 min(一开始只有起点)周围可以到达的方格(可到达的意思是其不是障碍物,也不存 在关闭列表中的方格,即不是已走过的方格)。计算 min 周围可到达的方格的 F 值。将还没在 openList 中点放入其中, 并 设置它们的"父方格"为点 min,表示他们的上一步是经过 min 到达的。如果 min 下一步某个可到达的方格已经在 openList 列表那么并且经 min 点它的 F 值更优,则修改 F 值并把其"父方格"设为点 min。3. 把 2 中的点 min 从"开启列表"中删除并存入"关闭列表"closeList 中, closeList 中存放的都是不需要再次检查的方格。如 果 2 中点 min 不是终点并且开启列表的数量大于零,那么继续从第 2 步开始。如果是终点执行第 4 步,如果openList 列表数量为零,那么就是找不到有效路径。4.如果第 3 步中 min 是终点,则结束查找,直接追溯父节点到起点的路径即为所选路径。
1)二维图中结点数据结构可定义为:
- typedef struct _Point
- {
- int x, y;
- int F, G, H;//F=G+H
- struct _Point *parent;
- }Point;
2)找出目标结点
- static Point *FindPath(Point *startPoint, Point *endPoint)
- {
- openList.push_back(AllocPoint(startPoint->x,startPoint->y));
-
- while (!openList.empty())
- {
- //1.第一步 取openlist中的F最小值
- Point *curPoint = GetLeastPoint();
-
- //2.将当前结点加入到closelist中
- openList.remove(curPoint);
- closeList.push_back(curPoint);
-
- //3.找到当前结点周围可达的节点 并计算F值
- vector<Point *>surroundPoints = GetSurroundPoints(curPoint);
- for (vector<Point *>::const_iterator it= surroundPoints.begin();it!= surroundPoints.end();it++)
- {
- Point *target = *it;
- Point *exsit = isInList(openList, target);
- if (!exsit)//如果可达结点不在openList中,则直接加入openList链表
- {
- target->parent = curPoint;
- target->G = calcDistance(curPoint, target);
- target->H = calcDistance(target, endPoint);
- target->F = target->G + target->H;
- openList.push_back(target);
- }
- else
- //如果可达结点已经在openList中,则重新计算F值,如果小于原F值,则改变其父节点为当前结点,G、F
- //值随之改变
- {
- int tmpG = calcDistance(curPoint, target);
- if (tmpG<target->G)
- {
- exsit->parent = curPoint;
- exsit->G = tmpG;
- exsit->F = tmpG + exsit->H;
- }
-
- delete target;
- }
- }
- surroundPoints.clear();
- Point *resPoint = isInList(openList, endPoint);
- if (resPoint)
- return resPoint;
- }
-
- }

3)通过目标结点的父节遍历链表找到开始结点,以获得正确路径
- /*返回正确路径*/
- list<Point*> GetPath(Point *startPoint, Point *endPoint)
- {
- Point *result = FindPath(startPoint, endPoint);
-
- list<Point*> path;
-
- //返回路径,如果没有找到路径则返回空链表
- while (result)
- {
- path.push_front(result);
- result = result->parent;
- }
- return path;
- }
运行截图:
由此也可知,A*算法所得结果并非最短路径
AStar.h
- #pragma once
- #include<list>
- #include<vector>
-
- using namespace std;
-
- const int kCost1 = 10;//直移一格消耗
- const int kCost2 = 14;//斜移一格消耗
-
- typedef struct _Point
- {
- int x, y;
- int F, G, H;//F=G+H
- struct _Point *parent;
- }Point;
-
- /*分配一个格子*/
- Point *AllocPoint(int x, int y);
- /*初始化地图*/
- void InitAstarMaze(int *Maze, int lines, int colums);
- /*A*算法寻找路径*/
- list<Point*> GetPath(Point *startPoint, Point *endPoint);
- /*清理资源*/
- void ClearAstarMaze();
-

AStar.cpp
- #include<math.h>
- #include"AStar.h"
- #include <iostream>
- #include <vector>
-
- static int *maze;//地图
- static int cols;//列数
- static int lines;//行数
-
- static list<Point*>openList;
- static list<Point*>closeList;
-
- /*A*算法寻找路径*/
- Point * isInList(const list<Point *> point, const Point *target);
- static Point *GetLeastPoint();//找出openlist中F值最小的节点
- static vector<Point*> GetSurroundPoints(const Point *point);//找到当前结点周围可达的节点
- bool isCanreach(const Point *point, const Point *target);//判断这两点是否可达
- int calcDistance(Point *target, Point *endPoint);
- static Point *FindPath(Point *startPoint, Point *endPoint)
- {
- openList.push_back(AllocPoint(startPoint->x,startPoint->y));
-
- while (!openList.empty())
- {
- //1.第一步 取openlist中的F最小值
- Point *curPoint = GetLeastPoint();
-
- //2.将当前结点加入到closelist中
- openList.remove(curPoint);
- closeList.push_back(curPoint);
-
- //3.找到当前结点周围可达的节点 并计算F值
- vector<Point *>surroundPoints = GetSurroundPoints(curPoint);
- for (vector<Point *>::const_iterator it= surroundPoints.begin();it!= surroundPoints.end();it++)
- {
- Point *target = *it;
- Point *exsit = isInList(openList, target);
- if (!exsit)
- {
- target->parent = curPoint;
- target->G = calcDistance(curPoint, target);
- target->H = calcDistance(target, endPoint);
- target->F = target->G + target->H;
- openList.push_back(target);
- }
- else
- {
- int tmpG = calcDistance(curPoint, target);
- if (tmpG<target->G)
- {
- exsit->parent = curPoint;
- exsit->G = tmpG;
- exsit->F = tmpG + exsit->H;
- }
-
- delete target;
- }
- }
- surroundPoints.clear();
- Point *resPoint = isInList(openList, endPoint);
- if (resPoint)
- return resPoint;
- }
-
- }
-
- void InitAstarMaze(int *arr,int _lines, int colums)
- {
- maze = arr;
- cols = colums;
- lines = _lines;
- }
-
- Point * AllocPoint(int x, int y)
- {
- Point * tmp = new Point;
- memset(tmp, 0, sizeof(Point));
- tmp->x = x;
- tmp->y = y;
- return tmp;
- }
-
- /*返回正确路径*/
- list<Point*> GetPath(Point *startPoint, Point *endPoint)
- {
- Point *result = FindPath(startPoint, endPoint);
-
- list<Point*> path;
-
- //返回路径,如果没有找到路径则返回空链表
-
- while (result)
- {
- path.push_front(result);
- result = result->parent;
- }
-
- return path;
- }
-
- static Point *GetLeastPoint()
- {
- Point *resPoint = openList.front();
- if (!openList.empty())
- {
-
- for (list<Point *>::const_iterator it= openList.begin();it!=openList.end();it++)
-
- if ((*it)->F < resPoint->F)
- {
- resPoint = *it;
- }
- }
-
- return resPoint;
- }
-
- static vector<Point*> GetSurroundPoints(const Point *point)
- {
- vector<Point *> surroundPoints;
-
- for (int x= point->x-1;x<= point->x+1;x++)
- for (int y = point->y - 1; y <= point->x+1; y++)
- {
- Point *tmp = AllocPoint(x, y);
- if (isCanreach(point,tmp))
- {
- surroundPoints.push_back(tmp);
- }
- else
- {
- delete tmp;
- }
- }
- return surroundPoints;
- }
-
- Point * isInList(const list<Point *> point,const Point *target)
- {
- for (list<Point *>::const_iterator it = point.begin(); it != point.end(); it++)
- {
- if ((*it)->x==target->x && (*it)->y==target->y)
- {
- return *it;
- }
- }
- return NULL;
- }
- bool isCanreach(const Point *point, const Point *target)
- {
- if (target->x<0|| target->x>(lines-1)
- || target->y<0|| target->y>(cols-1)
- || maze[target->x*cols+target->y]==1//1代表无法走的格子
- || maze[target->x*cols + target->y] == 2//2代表无法走的格子
- || (target->x==point->x && target->y==point->y)
- || isInList(closeList,target)!=NULL)
- {
- return false;
- }
-
- if (abs(point->x - target->x) + abs(point->y - target->y) == 1)
- return true;
- else
- return false;
- }
-
-
- int calcDistance(Point *target, Point *endPoint)
- {
- return abs(target->x - endPoint->x) + abs(target->y - endPoint->y);
- }
-
- void ClearAstarMaze()
- {
- maze = NULL;
- lines = cols = 0;
- for (list<Point *>::iterator it=openList.begin();it!=openList.end();)
- {
- delete *it;
- it = openList.erase(it);
- }
-
- for (list<Point *>::iterator it = closeList.begin(); it != closeList.end();)
- {
- delete *it;
- it = closeList.erase(it);
- }
- }

main.cpp
- #include <iostream>
- #include "AStar.h"
- #include<windows.h>
- int main()
- {
-
- int map[13][13] = {
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
- { 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, },
- { 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, },
- { 0, 1, 0, 1, 0, 1, 2, 1, 0, 1, 0, 1, 0, },
- { 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, },
- { 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, },
- { 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, },
- { 2, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 2, },
- { 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, },
- { 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, },
- { 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, },
- { 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } };
-
- InitAstarMaze(&map[0][0], 13, 13);
- Point *start = AllocPoint(12, 12);
- Point *end = AllocPoint(0, 0);
- list <Point*> path = GetPath(start, end);
- for (list<Point*>::iterator it = path.begin(); it != path.end(); it++)
- {
- Point *res = *it;
- cout << "(" << res->x << "," << res->y << ")" << endl;
- Sleep(800);
- }
- ClearAstarMaze();
- }

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。