关于A 星算法的研究与简单分析及其实现
Hanzack@163.com
(本文为自己所写例子为本人所创,欢迎批评指责,大家一起讨论,若转载请注明作者)
A星算法:从起始点开始,找它的所有子节点,加入到一个特殊队列priorityQueue(简称pQ)中(类似于一个数组)。 然后利用一个特殊函数对这些点进行打分, 这个特殊函数我们简单称为启发函数。 根据打分选出最好的点。 把这个节点从pQ队列中删除,并把这个节点的的所有子节点加入到pQ队列中。 循环这个步骤 知道找到到达终点的最短路径。
几个简单小问题:
1. 当一个节点没有子节点的时候怎么办?
不可能没有, B连接D, 那么互为子节点。
2. 当一个节点的子节点为目的点时候,怎么找到到达该目的点过程中的所有节点?
每一个节点都要封装为一个对象,存储着自己的父节点。由于每一个节点都可能有几个父节点,此时我们只要存储:在最短路径上该点的上一个节点为父节点即可。
(根据打分来看,该点是从哪一点过来的,那么就存储那一点为父节点)
二:
A星算法的简单图文描述:
先把A点加入队列pQ, 然后找到A点的子节点B, C, D 数字表示分数(这里数字越小表示越好)。然后把队列中的A点删除放入到一个封闭队列 close中(理解为一个叫做close的数组变量或者集合变量)。
然后从队列pQ,中找到分数最好的点, 这时候明显选B点,然后把E,F点加入到pQ队列中。并且把B移动到封闭队列中。 此时pQ中有如下几个点: C, D, E, F。 显然分数最好的是C点, 然后。。。。。。重复上述行为,直到找到终点。
简单来说,找到一个点,把它的子节点加入队列,再从队列中所有点中找到分数最好的点,循环。
三:理解大致理论后的难点。
而在做代码实现时,涉及的难点为:
1. 每次找一个点的子节点的时候不能直接把子节点直接全部加入到队列中:
a. 由于无向图中相连节点互为子节点, 所以先判断该子节点是否已经在close队列中了(就是要先判断是否已经被访问过了)。
b. 还要判断该子节点是否已经在pQ队列中,因为它也有可能是别人的子节点,而已经被加入到了pQ中。
c. 那么如果都不是,就可以加入到pQ队列中了。
d. 否则,是不是不用考虑它直接看下一个子节点呢? 不是,而是要做条件判断做其他考虑。
2. 关于pQ队列, 写一个pQ的类用来按照分数的好坏来排序pQ队列中的对象(这里存储的是节点)。这个类的写法可以参考stack的原理。 把stack的先进后出FILO 原理改为,进来了按照分数决定先出后出。
3. 书写一个节点类,每一个节点都是一个打包好的对象,有属性:父节点, 权值()
四: 最需要看的案例-----详细告诉你以下原因
1. 为什么在把子节点加入到队列中前需要检查该节点是否已经在于队列中?
2. 为什么为什么在把子节点加入到队列中前需要检查该节点是否已经在于封闭列表里,如果在封闭列表里,为什么又会产生把它从封闭列表里面拉出来的情形。
逻辑如下:
此处使用的函数为 F=g + h,每一个点的分值函数都是F. 其中 g:从起点开始经由过路点到该点的距离, h是一个估值函数,此处使用的估值函数为欧几里得距离,即从该点到目的点X的直线距离(为什么使用这个函数,因为这个距离是两点可能的最小距离。请自行查看启发函数的目的和用处)
1. A.由图和分值函数F可以看出,第一点为A点, 它的F值=g+h=0(从起始点A到A点的距离为0)+ A到X的距离。 Fa=1000 B. Fb=AB距离+BX距离 为600 C. Fc=AC+CX 为670 2. 当由A点开始,先把A点的子节点找出来暂时先不放到队列中,并把A点放入到封闭队列close中去。现在开始检查子节点是否可以并且怎样的方式进入队列
|