A STAR的实现和应用(c++版) 上
2006-10-27 18:33
337 查看
这是我第一次blog,写的不好不对的地方请大家一定批评指正.
最近看到论坛上在讨论a*算法,恰好忙完一个项目有空,就花了几天时间研修了一下A*算法.就把一些感想和代码贴上来跟大家分想交流.
一, 一些数据结构.
1,迷宫 二维数组 typedef vector<vector<element> > MAZE;
2,OpenList 用heap实现. my::Heap<element> hp; 另一个版本用list实现 typedef list<element> LE; 具体用宏USE_LIST 控制.
3,CloseList 用vector实现 VE close_list;(因为只涉及到插入(只在末端操作)和查找,所以从各方面考虑vector是最佳选择);
4,元素element看上去有点复杂,其实只是为了对元素进行比较,查找的操作而重载了几个运算符.具体见element.h
#ifndef ELEMENT_H__
#define ELEMENT_H__
#define START 'S'
#define END 'E'
#define WAY '#'
#define BLANK ' '
#define WALL '1'
struct location
...{
int x;
int y;
location(int xx=0,int yy=0):x(xx),y(yy)...{}
location& operator= (const location& other)
...{
if(this == &other)
return *this;
else
...{
this->x = other.x;
this->y = other.y;
}
return *this;
}
};
class element...{
public:
char terrain;
int dir;//no use now
int g;// have pass;
int h;// futher;
location pos;
element* father;
public:
element(char t=BLANK,int d=0,int gg=0,int hh=0,element* ff=NULL,location ll=location()):terrain(t),dir(d),g(gg),h(hh),father(ff)
...{pos.x = ll.x;pos.y=ll.y;}
bool operator==(const element& rth)...{return ((*this).pos.x==rth.pos.x && (*this).pos.y==rth.pos.y);}
element& operator= (const element& other)
...{
if(this == &other)
...{
return *this;
}
terrain = other.terrain;
dir = other.dir;
g = other.g;
h = other.h;
pos = other.pos;
father = other.father;
return *this;
}
bool operator<(const element& rhs)
...{
return (this->g+this->h) < (rhs.g+rhs.h);
}
bool operator>(const element& rhs)
...{
return (this->g+this->h) > (rhs.g+rhs.h);
}
friend ostream& operator<<(ostream& os,const element& ele)
...{
return os<< (ele.g + ele.h);
}
};
template <class T>
struct COMPARE
...{
bool operator()( T ta,T tb)
...{
return (ta.g + ta.h) < (tb.g + tb.h);
}
};
#endif
二.a*算法.
有了上面的数据结构,我们可以比较方便的来描述a*了.a*算法是一种启发式算法.他总会选择到达目标最短的路径. 一般的回溯很忙目.element.g 表示当前节点已走过的路径.element.h表示到达目标还需要走的路径.所以h是未知的,只是一种估计,好的设计应该在h的计算上下功夫.每次所选的下个节点都是g+h是最小的,即成本最小.本算法采用对角线权14,领边10.h的估算中忽律了地图上不可达的因素.简单 h = ads(end.pos - cur.pos);具体的 a*算法描述:
1) Add the starting square (or node) to the open list.
2) Repeat the following:
a) Look for the lowest F cost square on the open list. We refer to this as the current square.
b) Switch it to the closed list.
c) For each of the 8 squares adjacent to this current square …
If it is not walkable or if it is on the closed list, ignore it. Otherwise do the following.
If it isn’t on the open list, add it to the open list. Make the current square the parent of this square. Record the F, G, and H costs of the square.
If it is on the open list already, check to see if this path to that square is better, using G cost as the measure. A lower G cost means that this is a better path. If so, change the parent of the square to the current square, and recalculate the G and F scores of the square. If you are keeping your open list sorted by F score, you may need to resort the list to account for the change.
d) Stop when you:
Add the target square to the closed list, in which case the path has been found (see note below), or
Fail to find the target square, and the open list is empty. In this case, there is no path.
3) Save the path. Working backwards from the target square, go from each square to its parent square until you reach the starting square. That is your path.
就这么简单.按部就班就好了,具体代码见A-Star.cpp 的bool search_path(MAZE& maze)函数.
三 OpenList的实现:
本来我是用list来维护open list 的,但是为了维护list的有序性算法开销是巨大的,特别当数据是海量的时候.这时bianry heap是很好的选择,因为他只是基本有序,且能完全满足我们的要求.stl的heap或 prority_queue是很好的选择.但是这些东东功能有限,不能满足
If it is on the open list already, check to see if this path to that square is better, using G cost as the measure. A lower G cost means that this is a better path. If so, change the parent of the square to the current square, and recalculate the G and F scores of the square. If you are keeping your open list sorted by F score, you may need to resort the list to account for the change. 这一条. 所以只好自己动手写一个heap了.heap的实现具体见heap.h.如果你对heap不了解,赶紧去温故一下严为名的<<数据结构>>和老猴的<<stl源码剖析>>.
4,maze的实现.
本算法是比较稳定成熟的maze生成代码.你可以动态生成maze,也可以手动编辑MazeData.txt文件.由于本文重点 要介绍的 A Star 算法,就不再喧宾夺主地详细介绍了,具体代码可参见maze.cpp和maze.h
好了,马上就要下班了,下次我会接着写完并把代码贴上来(晕,怎么直接上传文件啊.).
最近看到论坛上在讨论a*算法,恰好忙完一个项目有空,就花了几天时间研修了一下A*算法.就把一些感想和代码贴上来跟大家分想交流.
一, 一些数据结构.
1,迷宫 二维数组 typedef vector<vector<element> > MAZE;
2,OpenList 用heap实现. my::Heap<element> hp; 另一个版本用list实现 typedef list<element> LE; 具体用宏USE_LIST 控制.
3,CloseList 用vector实现 VE close_list;(因为只涉及到插入(只在末端操作)和查找,所以从各方面考虑vector是最佳选择);
4,元素element看上去有点复杂,其实只是为了对元素进行比较,查找的操作而重载了几个运算符.具体见element.h
#ifndef ELEMENT_H__
#define ELEMENT_H__
#define START 'S'
#define END 'E'
#define WAY '#'
#define BLANK ' '
#define WALL '1'
struct location
...{
int x;
int y;
location(int xx=0,int yy=0):x(xx),y(yy)...{}
location& operator= (const location& other)
...{
if(this == &other)
return *this;
else
...{
this->x = other.x;
this->y = other.y;
}
return *this;
}
};
class element...{
public:
char terrain;
int dir;//no use now
int g;// have pass;
int h;// futher;
location pos;
element* father;
public:
element(char t=BLANK,int d=0,int gg=0,int hh=0,element* ff=NULL,location ll=location()):terrain(t),dir(d),g(gg),h(hh),father(ff)
...{pos.x = ll.x;pos.y=ll.y;}
bool operator==(const element& rth)...{return ((*this).pos.x==rth.pos.x && (*this).pos.y==rth.pos.y);}
element& operator= (const element& other)
...{
if(this == &other)
...{
return *this;
}
terrain = other.terrain;
dir = other.dir;
g = other.g;
h = other.h;
pos = other.pos;
father = other.father;
return *this;
}
bool operator<(const element& rhs)
...{
return (this->g+this->h) < (rhs.g+rhs.h);
}
bool operator>(const element& rhs)
...{
return (this->g+this->h) > (rhs.g+rhs.h);
}
friend ostream& operator<<(ostream& os,const element& ele)
...{
return os<< (ele.g + ele.h);
}
};
template <class T>
struct COMPARE
...{
bool operator()( T ta,T tb)
...{
return (ta.g + ta.h) < (tb.g + tb.h);
}
};
#endif
二.a*算法.
有了上面的数据结构,我们可以比较方便的来描述a*了.a*算法是一种启发式算法.他总会选择到达目标最短的路径. 一般的回溯很忙目.element.g 表示当前节点已走过的路径.element.h表示到达目标还需要走的路径.所以h是未知的,只是一种估计,好的设计应该在h的计算上下功夫.每次所选的下个节点都是g+h是最小的,即成本最小.本算法采用对角线权14,领边10.h的估算中忽律了地图上不可达的因素.简单 h = ads(end.pos - cur.pos);具体的 a*算法描述:
1) Add the starting square (or node) to the open list.
2) Repeat the following:
a) Look for the lowest F cost square on the open list. We refer to this as the current square.
b) Switch it to the closed list.
c) For each of the 8 squares adjacent to this current square …
If it is not walkable or if it is on the closed list, ignore it. Otherwise do the following.
If it isn’t on the open list, add it to the open list. Make the current square the parent of this square. Record the F, G, and H costs of the square.
If it is on the open list already, check to see if this path to that square is better, using G cost as the measure. A lower G cost means that this is a better path. If so, change the parent of the square to the current square, and recalculate the G and F scores of the square. If you are keeping your open list sorted by F score, you may need to resort the list to account for the change.
d) Stop when you:
Add the target square to the closed list, in which case the path has been found (see note below), or
Fail to find the target square, and the open list is empty. In this case, there is no path.
3) Save the path. Working backwards from the target square, go from each square to its parent square until you reach the starting square. That is your path.
就这么简单.按部就班就好了,具体代码见A-Star.cpp 的bool search_path(MAZE& maze)函数.
三 OpenList的实现:
本来我是用list来维护open list 的,但是为了维护list的有序性算法开销是巨大的,特别当数据是海量的时候.这时bianry heap是很好的选择,因为他只是基本有序,且能完全满足我们的要求.stl的heap或 prority_queue是很好的选择.但是这些东东功能有限,不能满足
If it is on the open list already, check to see if this path to that square is better, using G cost as the measure. A lower G cost means that this is a better path. If so, change the parent of the square to the current square, and recalculate the G and F scores of the square. If you are keeping your open list sorted by F score, you may need to resort the list to account for the change. 这一条. 所以只好自己动手写一个heap了.heap的实现具体见heap.h.如果你对heap不了解,赶紧去温故一下严为名的<<数据结构>>和老猴的<<stl源码剖析>>.
4,maze的实现.
本算法是比较稳定成熟的maze生成代码.你可以动态生成maze,也可以手动编辑MazeData.txt文件.由于本文重点 要介绍的 A Star 算法,就不再喧宾夺主地详细介绍了,具体代码可参见maze.cpp和maze.h
好了,马上就要下班了,下次我会接着写完并把代码贴上来(晕,怎么直接上传文件啊.).
相关文章推荐
- A STAR的实现和应用(c++版) 下
- LoadRunner简单应用之:C++ DLL的实现及调用
- 【C++ STL应用与实现】16: 迭代器综述
- 对于一个频繁使用的短小函数,在C语言中应用什么实现,在C++中应用什么实现?
- 【C++ STL应用与实现】18: 怎样使用迭代器适配器
- C/C++ 第八周串和数组 (一)对称矩阵压缩存储的实现与应用 项目3—(2)
- 数据结构学习系列三-单向循环链表(c++实现且应用模板)
- 【C++ STL应用与实现】62: 如何使用std::next_permutation
- C# 实现C/C++共同体简单应用
- C++模板应用——让模板定义和实现分离的方法
- C++模板应用——在类模板实现中引用其内部定义的复合数据类型
- 用C编写一个模拟实现C++多态应用的一个范例
- 哈希表的应用(C++实现)
- 对于一个频繁使用的短小函数,在C语言中应用什么实现,在C++中应用什么实现?
- C++ 模板应用 实现一个Queue 队列
- 数制转换-栈的应用(C++实现)
- 【C++ STL应用与实现】26: 如何使用std::for_each以及基于范围的for循环 (since C++11)
- 【C++ STL应用与实现】5: 如何使用std::array (since C++11)
- 【C++ STL应用与实现】目录
- 字典树的C++实现以及应用