A*(A-Star) 算法 是一种静态路网中求解最短路最有
   A star算法在静态路网中的应用

A star算法在静态路网中的应用

效的方法。
 
  公式表示为: f(n)=g(n)+h(n),
 
  其中 f(n) 是从初始点经由节点n到目标点的估价函数,
 
  g(n) 是在状态空间中从初始节点到n节点的实际代价,(即N点到起始位置的)
 
  h(n) 是从n到目标节点最佳路径的估计代价(用于启发选取待处理的点)。
 
  保证找到 最短路径 (最优解的)条件,关键在于估价函数h(n)的选取:
 
  估价值h(n)<= n到目标节点的距离实际值,这种情况下,搜索的点数多,搜索范围大,效率低。但能得到最优解。
 

  如果 估价值>实际值, 搜索的点数少,搜索范围小,效率高,但不能保证得到最优解。

 

 

估价值与实际值越接近,估价函数取得就越好

  例如对于几何路网来说,可以取两节点间欧几理德距离(直线距离)做为估价值,即f=g(n)+sqrt((dx-nx)*(dx-nx)+(dy-ny)*(dy-ny));这样估价函数f在g值一定的情况下,会或多或少的受估价值h的制约,节点距目标点近,h值小,f值相对就小,能保证最短路的搜索向终点的方向进行。明显优于Dijkstra 算法 的毫无无方向的向四周搜索。

 

 

算法伪代码:

 

 主要搜索过程伪代码如下:

  创建两个表,OPEN表保存所有已生成而未考察的节点(保存这个函数的f(n)值与g(n)值),CLOSED表中记录已访问过的节点(只是为了防止重复访问)。 

 

  算起点的估价值;//起始值假设为0

  将起点放入OPEN表;//open表起始值为空,随着不断的进行子节点处理,表中值越来越多

while(OPEN!=NULL) 

{ 

从OPEN表中取f(n)最小的节点n;//且这个节点不在closed表中 

if(n节点==目标节点)

{ 

break; 

} 

for(当前节点n 的每个子节点X) //即图中与n节点连接的节点

{

算X的f(n)值;//即n点open值g(n)+n到x的距离+x的估计值 

/*在处理X节点时,假设有m个与其连接的节点已经获取到从0节点到此节点的最短路径,则当前的N节点一定是其中的最短节点,因为N节点的选择依据就是路径最短。而对于与x连接,当前还未处理的节点,在之后处理到那个节点时,会进入X in OPEN语句中,如果这个节点比现在的N还短,那么会更新X值的信息。

 疑问:如果节点B按照A节点的路径计算g(n),然后A节点被更新后,是否还需要更新B节点?

 答:B按照A进行计算,则A一定是在CLOSED表中的已处理点(即A是B的父节点,子节点OPEN值的计算一定是在父节点的处理回合中进行,所以A一定已经进行了处理)。然而,疑问中提到的假设为A节点被更新,则在更新后A到起始节点的路径中的各个节点的f(n)都小于等于更新前N节点的f(n)(如果不是小于等于,那么也没必要更新了),由于这个路径是在A处理后得出的,那么在处理A之前,一定存在某个节点是在OPEN中,但却没有处理过(不在CLOSED表),如果是这样的话,在当初处理A的时候,这个节点小于A,A一定不会被选中。由此可知,疑问中的情况是不可能出现的。也就是说,A被处理后,A的值不会被更新。节点只有被当做子节点处理中才可能被更新。*/

   if(X in OPEN)

   { 

   if( X的f(n)小于OPEN表的f(n) )

{ 

   把n设置为X的父亲; 

   更新OPEN表中的f(n); //取最小路径的估价值 

   }

   }

   if(X in CLOSE) 

{ 

   continue;

   }

   if(X not inboth)

{ 

   把n设置为X的父亲;

   求X的f(n); 

   并将X插入OPEN表中; //还没有排序 

   }

   }//end for

   将n节点插入CLOSE表中; 

   按照f(n)将OPEN表中的节点排序; //实际上是比较OPEN表内节点f的大小,从最小路径的节点向下进行。

  }//end while(OPEN!=NULL)

 

  保存路径,即 从终点开始,每个节点沿着父节点移动直至起点,这就是你的路径;