标签:
最近闲来无事想实现一下A*算法,其实例子在网上已经很多了。我只是想自己动手试试,如果效率还行的话可以保存起来以便日后使用。
A*算法的基本原理可以参考这里:
本文只是对实现A*算法中遇到的问题和解决思路进行总结记录。为了速度我使用了二叉堆的方法。
在第一个版本完成后我进行了测试,在100*100的格子里从左上角搜索到右下角居然需要0.6秒之久!然后我使用Visual Studio的性能和诊断功能,发现大量时间被消耗在了判断位置是否在开启列表和关闭列表中。以前的方法是用两个vector来存放开启列表和关闭列表的位置信息,然后遍历容器来判别是否在其中,效率自然很低。然后我就改变方法,构建一个和地图行、列一样的二维数组来存放位置的状态信息,这样我直接通过当前的x和y坐标就能够直接判断是否在开启列表或关闭列表中了。最后测试发现效率的确提高了非常多!
然后再打开Visual Studio的性能和诊断工具观察,发现在开启列表中发现更近的路径时,需要更新G值的时候。这时候效率就非常低,因为我之前的做法是在这里重新构建一个二叉堆,效率自然就低了。这里解决比较简单,只需要把当前节点进行上滤就好了。不过这个std里面没提供这个,自己实现了一下,具体可以参考百度一下二叉堆。
再测试一下速度还挺满意的,再看看有没有需要优化的地方。刚才在解决判断位置是否在开启/关闭列表的时候,我使用了一个二维数组来存放状态信息。对二维数组的访问时比较慢的,特别是在访问频繁的时候,这里我改为了一维数组。
然后我又发现了一个问题,在搜索过程中我需要经常new 一个对象出来存放位置信息,在地图比较大的时候效率就比较低了。为了不经常创建对象我又整了一个小对象分配器来。听说box2d这个物理引擎就使用了一个小对象分配器,遂翻它源码看了一下,发现还是蛮适合这里的情况的,然后就把它弄了过来。测试之后发现效果提升明显,在1000*1000的地图里从左上角搜索到右下角需要0.3秒以上,使用了小对象分配器后只需要0.1几秒。
下面给出测试数据:
地图大小 | 允许斜走 | 耗时 |
100*100 | 否 | 0.001s |
100*100 | 是 | 0.000s |
1000*1000 | 否 | 0.137s |
1000*1000 | 是 | 0.006s |
代码下载:https://github.com/zhangpanyi/AStar
标签:
原文地址:http://www.cnblogs.com/jiushichenan/p/4380009.html