A*搜索算法

A*搜索算法是一种结合Dijkstra算法和BFS最佳优先搜索的最短路径算法,适用于有障碍物的图。算法通过评估函数选择优先级处理节点,其中F=G+H,G是从起点到节点的实际代价,H是预测到终点的代价。优化包括采用优先队列和HashSet处理节点更新,以及针对不同结构的图进行邻接节点查找和H值计算。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

参考:
A星算法详解(个人认为最详细,最通俗易懂的一个版本)
最短路径A*算法原理及java代码实现(看不懂是我的失败)

算法简介

A*搜索算法结合了基于广度搜索的Dijkstra算法和贪心思想的BFS最佳优先搜索的优点设计的最短路径算法,他可以用于含有障碍物的图算法之中。其思想是首先将节点的邻近节点加入带处理队列之中,但是并不是依次处理,而是通过一个评估函数,依据该函数有优先级地对待处理队列中的节点进行处理。这样就能较为快速的找到终点。

算法思想

首先要将节点分类,分为可通行节点,不可通行节点,起始节点和终点。然后节点应该还含有的参数是父节点的指针。
从起点开始,首先搜寻与起点相邻的节点,将其加入待检查队列openlist中。然后进入循环,从openList中取出一个点,取出原则后面介绍,将该节点加入closeList中。由于当前只有起点,因此取出的就是起点。然后将与起点相连的点(不加入路障点和在closeList中的点)加入openList中,并且在加入过程中,要计算每个点的评估函数值F,该值是作为前面提到的从openList中取点原则的依据(取F最小的点)。F=G+H,其中G为从起始节点到该点所要花费的总的代价,H为该点到终点的预测代价。在加入点到openList的过程中,如果该点的父节点为空,则还要将加入点的父节点指定为当前节点;若父节点不为空(说明带加入点已经在openList之中了,此时要做到就是是否更新带加入点的状态),则要比较从当前节点到带加入点的G值还是带加入点的已有G值大,若前者大,则将更新G值和带加入点的父节点,否则不改变带加入点的状态。循环以上操作直至终点加入到openList之中。最后,根据终点的父节点指针,依次找到起始节点。

算法伪代码

main(){
    openList.add(startNode)
    while(!openList.isEmpty()){
        node = openList.getMinFNode();      //opt1
        closeList.add(node);
        if(node==endNode){
            isFind = true;
            break;
         }
       addAdjacentNode(node);                 //opt2
    }
    getTrace();
}
addAdjacentNode(curNode){
    nodeList = getAdjacentNode(curNode);        //opt3
    for(node belong nodeList){
        calculate of update F of node;                     //opt4
        openList.add(node);                                     //opt5
    }
}

优化

opt1

getMinFNode方法可以将openList采用优先队列的方式达到快速得到最小F的点。但是优先队列存在一个问题,就是无法快速的在opt5处更新已经在openList中的节点,因此要配合HashSet使用,所有该数据结构最好自己实现。

opt2

将邻居节点插入openList中时要做一系列工作,比如寻找得到临近节点列表,计算每个临近节点的f值(包含计算H和计算/更新G),将节点加入openList。

opt3

在下面具体实现的代码中,我们采取的节点为方块形式,因此可以采用上下左右斜对角的8个方向进行查找,保证不会遗漏。但是如果对于树形结构的图,也可以采用遍历该节点的邻接链表方式,得到一系列相邻节点。

opt4

F值的计算主要是计算G(G值的计算主要是根据Dijkstra算法思想),如果该节点不在openList中,则直接计算G值并更新父节点;如果该节点在openList中,那么之前肯定计算过G值,此时就是要计算从上一节点lastNode到该节点的G值,并与原先的G值比较,如果新的G值小,则要跟新G值和将该点的父节点重新定向到lastNode上。在我们下面的实例中,G值默认为水平垂直花费为10,斜对角为14。但如果采用的是树形图,则要根据节点之间的权重进行计算(Dijkstra算法)。
H值的计算采用了最佳优先搜索的方法,在下面的实例中,我们采用的是忽略路障的曼哈顿距离来估计,当然也可以依据情况采用欧式距离,非欧距离等方式计算。对于树形图的H计算我暂时也不清楚,这也是我不打算将A星搜索算法用于树形图的原因(节点之间的连接数不确定)

opt5

如opt1中所述,要想用优先队列,就要解决如何在加入时保证加入点不重复,且能及时更新最小F的问题。这也是我没采用优先队列而使用了HashSet的原因(虽然在opt1中要遍历获得最小值f比较慢)

算法实现

Node.java

public class Node {
   
   
    int f;
    
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值