A*算法实际是个穷举算法,也与课本上教的最短路径算法类似。课本上教的是两头往中间走,也是所有路径都走一次,每一个点标注最短值。
- A* (使用曼哈顿距离)
2. A* (采用欧氏距离)
3. A* (利用切比雪夫距离)
4. Dijkstra
5. Bi-Directional Breadth-First-Search(双向广度优先搜索)
在最短路径搜寻效率上,一般有A*>Dijkstra、双向BFS,其中Dijkstra、双向BFS到底哪个算法更优,还得看具体情况。
A*算法最为核心的过程,就在每次选择下一个当前搜索点时,是从所有已探知的但未搜索过点中(可能是不同层,亦可不在同一条支路上),选取f值最小的结点进行展开。
而所有“已探知的但未搜索过点”可以通过一个按f值升序的队列(即优先队列)进行排列。
这样,在整体的搜索过程中,只要按照类似广度优先的算法框架,从优先队列中弹出队首元素(f值),对其可能子结点计算g、h和f值,直到优先队列为空(无解)或找到终止点为止。
A*算法与广度、深度优先和Dijkstra 算法的联系就在于:当g(n)=0时,该算法类似于DFS,当h(n)=0时,该算法类似于BFS。且同时,如果h(n)为0,只需求出g(n),即求出起点到任意顶点n的最短路径,则转化为单源最短路径问题,即Dijkstra算法。这一点,可以通过上面的A*搜索树的具体过程中将h(n)设为0或将g(n)设为0而得到。
BFS、DFS与A*搜寻算法的比较
参考了算法驿站上的部分内容:
不管以下论述哪一种搜索,都统一用这样的形式表示:搜索的对象是一个图,它面向一个问题,不一定有明确的存储形式,但它里面的一个结点都有可能是一个解(可行解),搜索的目的有两个方面,或者求可行解,或者从可行解集中求最优解。
我们用两张表来进行搜索,一个叫OPEN表,表示那些已经展开但还没有访问的结点集,另一个叫CLOSE表,表示那些已经访问的结点集。
蛮力搜索(BFS,DFS)
BFS(Breadth-First-Search 宽度优先搜索)
首先将起始结点放入OPEN表,CLOSE表置空,算法开始时:
1、如果OPEN表不为空,从表中开始取一个结点S,如果为空算法失败
2、S是目标解吗?是,找到一个解(继续寻找,或终止算法);不是到3
3、将S的所有后继结点展开,就是从S可以直接关联的结点(子结点),如果不在CLOSE表中,就将它们放入OPEN表末尾,而把S放入CLOSE表,重复算法到1。
DFS(Depth-First-Search 深度优先搜索)
首先将起始结点放入OPEN表,CLOSE表置空,算法开始时:
1、如果OPEN表不为空,从表中开始取一个结点S,如果为空算法失败
2、S是目标解吗?是,找到一个解(继续寻找,或终止算法);不是到3
3、将S的所有后继结点展开,就是从S可以直接关联的结点(子结点),如果不在CLOSE表中,就将它们放入OPEN表开始,而把S放入CLOSE表,重复算法到1。
是否有看出:上述的BFS和DFS有什么不同?
仔细观察OPEN表中待访问的结点的组织形式,BFS是从表头取结点,从表尾添加结点,也就是说OPEN表是一个队列,是的,BFS首先让你想到‘队列’;而DFS,它是从OPEN表头取结点,也从表头添加结点,也就是说OPEN表是一个栈!
DFS用到了栈,所以有一个很好的实现方法,那就是递归,系统栈是计算机程序中极重要的部分之一。用递归也有个好处就是,在系统栈中只需要存结点最大深度那么大的空间,也就是在展开一个结点的后续结点时可以不用一次全部展开,用一些环境变量记录当前的状态,在递归调用结束后继续展开。
https://blog.youkuaiyun.com/v_JULY_v/article/details/6093380
https://blog.youkuaiyun.com/v_JULY_v/article/details/6238029