基本定义

一种寻路算法,特点是:启发式的,效率高,基本思路比较简单。

用途

寻路。在指定的地图上,考虑到地图上的移动代价,找到最优的路径。

核心概念

开表,闭表,估值函数。

开表

开表,记录了当前需要处理的地图上的点。

1什么点会加入开表?

1.1    当一个点是起始点时,可以加入;

1.2    当一个点是起始点的邻接点,且不再闭表里时,可以进入开表;

2什么点会离开开表?

2.1开表中的点会按照f(n)进行升序排序,得到最小值的一个点被最先处理;当一个点已经处理后,会离开开表,加入闭表。

闭表

闭表,记录了当前已经处理的地图上的点。

1什么点会加入闭表?

1.1当一个点已经处理后,会加入闭表;

2什么点会离开闭表?

不会有点离开闭表。

估值函数

估值函数,估算了当前点处于最优路径上的代价。

估值函数f(n) = g(n) + h(n),其中g(n)表示由起点到当前点的代价;h(n)表示由当前点到终点的代价。A*算法的最核心部分也就是这个估值函数的设计。

在我的实现中,我用简单的几何距离作为估值函数的实现。

算法描述

1将起点加入开表

2开表里如果为空,算法退出;否则,取出f(n)最小的点作为最优路径上的点;

3针对当前处理的点,计算邻接点,如果邻接点不在闭表,且不在开表,加入开表

4重复2,3步骤直到退出

示例实现

  1. #coding=utf8
  2. """
  3. a* algorithm
  4. """
  5. import math
  6.  
  7. AB_MAP = [
  8. [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,],
  9. [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,],
  10. [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,],
  11. [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,],
  12. [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,],
  13. [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,],
  14. [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,],
  15. [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,],
  16. [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,],
  17. [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,],
  18. [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,],
  19. [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,],
  20. [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,],
  21. [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,],
  22. [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,],
  23. [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,],
  24. [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,],
  25. [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,],
  26. [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,],
  27. [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,],
  28. ]
  29. POS_UP = 1
  30. POS_LEFT = 2
  31. POS_DOWN = 3
  32. POS_RIGHT = 4
  33.  
  34. def mod_map(m_map, pos_x, pos_y, val):
  35. """
  36. 修改地图的某个点位的值
  37. """
  38. m_map[pos_x][pos_y] = val
  39.  
  40. def print_map(m_map):
  41. """
  42. 打印地图
  43. """
  44. rows = len(m_map)
  45. for i in range(0, rows - 1):
  46. cols = len(m_map[i])
  47. for j in range(0, cols - 1):
  48. print str(m_map[i][j]) + "\t",
  49. j = j + 1
  50. print
  51. i = i + 1
  52.  
  53. class Node(object):
  54. """
  55. 记录一个节点的信息
  56. """
  57. def __init__(self, x, y, h_n=0, g_n=0):
  58. self.pos_x = x
  59. self.pos_y = y
  60. self.parent = None
  61. self.h_n = h_n
  62. self.g_n = g_n
  63. self.f_n = self.h_n + self.g_n
  64.  
  65. def update_h_n(self, target):
  66. """
  67. 计算h(n)
  68. """
  69. self.h_n = int(math.sqrt((target.pos_x - self.pos_x)**2 + (target.pos_y - self.pos_y)**2))
  70. return self.h_n
  71.  
  72. def update_g_n(self, source):
  73. """
  74. 计算g(n)
  75. """
  76. self.g_n = int(math.sqrt((source.pos_x - self.pos_x)**2 + (source.pos_y - self.pos_y)**2))
  77. return self.g_n
  78.  
  79. def update_f_n(self, source, target):
  80. """
  81. 计算f(n)
  82. """
  83. self.f_n = self.update_g_n(source) + self.update_h_n(target)
  84. return self.f_n
  85.  
  86. def update_parent(self, par):
  87. """
  88. 更新父节点
  89. """
  90. self.parent = par
  91.  
  92. def get_adj_node(self, flag, source, target):
  93. """
  94. 计算邻近的节点
  95. """
  96. if flag == POS_UP:
  97. cur_node = Node(self.pos_x, self.pos_y - 1)
  98. cur_node.update_f_n(source, target)
  99. cur_node.parent = self
  100. return cur_node
  101. elif flag == POS_LEFT:
  102. cur_node = Node(self.pos_x - 1, self.pos_y)
  103. cur_node.update_f_n(source, target)
  104. cur_node.parent = self
  105. return cur_node
  106. elif flag == POS_DOWN:
  107. cur_node = Node(self.pos_x, self.pos_y + 1)
  108. cur_node.update_f_n(source, target)
  109. cur_node.parent = self
  110. return cur_node
  111. elif flag == POS_RIGHT:
  112. cur_node = Node(self.pos_x + 1, self.pos_y)
  113. cur_node.update_f_n(source, target)
  114. cur_node.parent = self
  115. return cur_node
  116. else:
  117. return None
  118.  
  119. def node_addible(node, open_list, close_list):
  120. """
  121. 判断一个点是否在open和close表
  122. """
  123. index = str(node.pos_x) + '_' + str(node.pos_y)
  124. if index not in open_list and index not in close_list:
  125. open_list[index] = node
  126.  
  127. def reach_end(node, target):
  128. """
  129. 判断一个点是否到达终点
  130. """
  131. if node and target and node.pos_x == target.pos_x and node.pos_y == target.pos_y:
  132. return True
  133. else:
  134. return False
  135.  
  136. def handle_reach_end(node, mmap, modval, print_path=False):
  137. """
  138. 当一个点到达终点时的处理方法
  139. """
  140. if node and mmap:
  141. while node:
  142. if print_path:
  143. print "x: %s, y: %s" % (node.pos_x, node.pos_y)
  144. mod_map(mmap, node.pos_x, node.pos_y, modval)
  145. node = node.parent
  146.  
  147. def main(source, target, open_list, close_list, mmap):
  148. """
  149. 主函数
  150. """
  151. open_list[str(source.pos_x) + '_' + str(source.pos_y)] = source
  152. while open_list:
  153. tmp_dict = sorted(open_list.iteritems(), key=lambda d: d[1].f_n)
  154. first_key = tmp_dict[0][0]
  155. first_node = open_list[first_key]
  156. del open_list[first_key]
  157.  
  158. up_node = first_node.get_adj_node(POS_UP, source, target)
  159. if reach_end(up_node, target):
  160. handle_reach_end(up_node, mmap, 2)
  161. break
  162.  
  163. left_node = first_node.get_adj_node(POS_LEFT, source, target)
  164. if reach_end(left_node, target):
  165. handle_reach_end(left_node, mmap, 2)
  166. break
  167.  
  168. down_node = first_node.get_adj_node(POS_DOWN, source, target)
  169. if reach_end(down_node, target):
  170. handle_reach_end(down_node, mmap, 2)
  171. break
  172.  
  173. right_node = first_node.get_adj_node(POS_RIGHT, source, target)
  174. if reach_end(right_node, target):
  175. handle_reach_end(right_node, mmap, 2)
  176. break
  177.  
  178. if first_key not in close_list:
  179. close_list[first_key] = first_node
  180.  
  181. node_addible(up_node, open_list, close_list)
  182. node_addible(down_node, open_list, close_list)
  183. node_addible(left_node, open_list, close_list)
  184. node_addible(right_node, open_list, close_list)
  185.  
  186. if __name__ == '__main__':
  187. print "******************************* before *******************************"
  188. print_map(AB_MAP)
  189. OPEN_LIST = {}
  190. CLOSE_LIST = {}
  191.  
  192. SOURCE = Node(3, 4)
  193. TARGET = Node(13, 9)
  194. main(SOURCE, TARGET, OPEN_LIST, CLOSE_LIST, AB_MAP)
  195.  
  196. print "******************************** after ********************************"
  197. mod_map(AB_MAP, SOURCE.pos_x, SOURCE.pos_y, 0)
  198. mod_map(AB_MAP, TARGET.pos_x, TARGET.pos_y, 0)
  199. print_map(AB_MAP)

参考文章

http://www.cnblogs.com/technology/archive/2011/05/26/2058842.html
http://blog.sciencenet.cn/blog-5422-538894.html
https://segmentfault.com/a/1190000004462060
http://blog.csdn.net/v_JULY_v/article/details/6093380
http://blog.csdn.net/zhuangxiaobin/article/details/38755447
http://www.cnblogs.com/tongy0/p/5671545.html

A*算法的理解与简单实现的更多相关文章

  1. SDUT OJ 数据结构实验之串一:KMP简单应用 && 浅谈对看毛片算法的理解

    数据结构实验之串一:KMP简单应用 Time Limit: 1000 ms Memory Limit: 65536 KiB Submit Statistic Discuss Problem Descr ...

  2. 量化交易中VWAP/TWAP算法的基本原理和简单源码实现(C++和python)(转)

    量化交易中VWAP/TWAP算法的基本原理和简单源码实现(C++和python) 原文地址:http://blog.csdn.net/u012234115/article/details/728300 ...

  3. Vue中diff算法的理解

    Vue中diff算法的理解 diff算法用来计算出Virtual DOM中改变的部分,然后针对该部分进行DOM操作,而不用重新渲染整个页面,渲染整个DOM结构的过程中开销是很大的,需要浏览器对DOM结 ...

  4. React中diff算法的理解

    React中diff算法的理解 diff算法用来计算出Virtual DOM中改变的部分,然后针对该部分进行DOM操作,而不用重新渲染整个页面,渲染整个DOM结构的过程中开销是很大的,需要浏览器对DO ...

  5. kNN算法python实现和简单数字识别

    kNN算法 算法优缺点: 优点:精度高.对异常值不敏感.无输入数据假定 缺点:时间复杂度和空间复杂度都很高 适用数据范围:数值型和标称型 算法的思路: KNN算法(全称K最近邻算法),算法的思想很简单 ...

  6. 1102: 零起点学算法09——继续练习简单的输入和计算(a-b)

    1102: 零起点学算法09--继续练习简单的输入和计算(a-b) Time Limit: 1 Sec  Memory Limit: 520 MB   64bit IO Format: %lldSub ...

  7. openCV中直方图均衡化算法的理解

    直方图均衡化就是调整灰度直方图的分布,即将原图中的灰度值映射为一个新的值.映射的结果直观表现是灰度图的分布变得均匀,从0到255都有分布,不像原图那样集中.图像上的表现就是对比度变大,亮的更亮,暗的更 ...

  8. 【repost】让你一句话理解闭包(简单易懂)

    接触javascript很久了,每次理解闭包都似是而非,最近在找Web前端的工作,所以需要把基础夯实一下. 本文是参照了joy_lee的博客 闭包 在她这篇博客的基础上以批注的形式力争把我的理解阐述出 ...

  9. Map集合遍历的四种方式理解和简单使用-----不能for循环遍历

    Map集合遍历的四种方式理解和简单使用   ~Map集合是键值对形式存储值的,所以遍历Map集合无非就是获取键和值,根据实际需求,进行获取键和值 1:无非就是通过map.keySet()获取到值,然后 ...

随机推荐

  1. iOS开发之如何修改导航栏的内容

    导航栏的内容由栈顶控制器的navigationItem属性决定. UINavigationItem有以下属性影响着导航栏的内容(通常在子控制器中viewDidLoad方法中调用这些方法): 左上角的返 ...

  2. 安装prometheus+grafana监控mysql redis kubernetes等

    1.prometheus安装 wget https://github.com/prometheus/prometheus/releases/download/v1.5.2/prometheus-1.5 ...

  3. Failed to connect to Xilinx hw_server. Check if the hw_server is running and correct TCP port is used.

    Failed to connect to Xilinx hw_server. Check if the  hw_server is running and correct TCP port is us ...

  4. JSP九大内置对象的作用和用法总结(转)

    SP中一共预先定义了9个这样的对象,分别为:request.response.session.application.out.pagecontext.config.page.exception 1.r ...

  5. jQuery购物车

    效果图 HTML代码:(非表格方式) <div class="nav2"> <input type="checkbox" class=&quo ...

  6. sass.scss简单入门

    最近研究了一下sass和scss,清晰结构化,在某些地方的确强大,所以写了一篇入门教程,大概15分钟左右就能明白基本原理 什么是sass(css预处理器) Sass官网上是这样描述sass的,sass ...

  7. ng自带的表单验证

    几点注意:使用ng的表单验证,需要给form,input,textarea一个name 要求:验证输入框的内容(长度,正则,必填,),当验证不通过的时候,就禁用提交按钮 使用的验证:ng-maxlen ...

  8. 【Egret】2D 使用中的一些疑难解决技巧!

    1.问题:声音在ios上无法播放    解决方法:①首先需要预加载一个声音                        ②然后目前只有点击之后才能播放声音,不能默认播放 2.问题:滚动条问题   解 ...

  9. LoonAndroid自动检测输入框 --- Author: rose && lvyerose@163.com

    LoonAndroid框架,同时给我们提供了一套自动检测输入规则的工具,用起来很是方便,下面介绍一下这个东东的使用方法(注意,该说明是基于项目已经集成了LoonAndroid框架而言,如果您未集成该框 ...

  10. 不忘初心 --- 重读<<The C Programming Language>>

    这篇文章应该发布在好几年前,2011年计算机界大师Dennis Ritchie仙逝,那时对大师的映象还停留在大一刚学编程时:Unix的合作开发者,C语言的发明人.通过网上的纪念文章<<Un ...