A*算法
一、简介
A*算法是启发式算法的一种,可以求出在图形平面上有着多个节点时,找到两个节点之间的最短路径,它的用到的地方还是挺多的,如游戏中的NPC移动,其实A*算法和Dijkstra算法很像很像的(个人相当感觉额,但也有一点点差异),如果你了解Dijkstra算法的话,那对于A*算法就很容易接受了。
二、算法主要内容
对于A*算法而言,需要设计一个估计函数,即f(n) = g(n) + h(n),其中g(n)表示搜索起点到当前节点的代价(通常用某节点在搜索树中的深度来表示的),h(n)表示当前节点到目标节点的估计值,对于A*算法的估计函数而言,其中h(n)的设计最为重要,也是衡量是否为A*算法的一个标准。
对于A*算法而言,需要满足一下几个条件才算得上A*算法:
1).图中存在从起点到目标终点的最有路径。
2).问题是有限的。
3).所有节点的子节点代价>0。
4).h(n) =< h*(n) (其中h*(n)为实际问题的代价值)
三、算法实现示意图
求V0->V5的路径,在V0->V5过程中,可以经过V1、V2、V3、V4到达目标及诶大V5
四、算法设计伪代码
将起点放入OPEN表;
while(OPEN!=NULL)
{
从OPEN表中取估价值f最小的节点n;
if(n节点==目标节点)
{
找到了目标
break;
}
for(当前节点n的每个子节点X)
{
算X的估价值;
if(X in OPEN)
{
if( X的估价值小于OPEN表的估价值 )
{
把n设置为X的父亲;
更新OPEN表中的估价值; //取最小路径的估价值
}
}
if(X in CLOSE)
{
continue;
}
if(X not in both)
{
把n设置为X的父亲;
求X的估价值;
并将X插入OPEN表中; //还没有排序
}
}//end for
将n节点插入CLOSE表中;
按照估价值将OPEN表中的节点排序; //实际上是比较OPEN表内节点f的大小,从最小路径的节点向下进行。
}//end while(OPEN!=NULL)
保存路径,即从终点开始,每个节点沿着父节点移动直至起点,这就是你的路径
五、A*算法和Dijkstra算法比较
这两个算法很相似,但一般A*算法的性能比Dijkstra算法好稍稍好一些,A*算法的时间复杂度为nlog(n),而Dijkstra算法为o(n2),这是因为在获得没有遍历的节点时,也就是在OPEN表中的那些,A*算法是对其用快速排序将其按照估计值的大小进行排序的,因而总时间复杂度为o(n)*log(n),其中o(n)外层遍历OPEN表的所有节点,但对于Dijkstra算法,它并没有对那些OPEN表的节点进行排序,所以得到的时间复杂度为o(n)*o(n)。