笔试算法题(48):简介 - A*搜索算法(A Star Search Algorithm)

A*搜索算法(A Star Search Algorithm)

  • A*算法主要用于在二维平面上寻找两个点之间的最短路径。在从起始点到目标点的过程中有很多个状态空间,DFS和BFS没有任何启发策略所以穷举所有的状
    态空间,不适合仅需对局部进行搜索的应用。启发式搜索的关键在于:当前节点在选择下一步节点的时候,可以通过一个启发函数进行选择,选择到达终点代价最小
    的节点作为下一步节点。A*的启发函数构造为:

    f(n)=g(n)+h(n)

    f(n)是可选的下一个节点的代
    价,g(n)表示从start点到n点的代价,h(n)表示从n点到end点的代价;但是h(n)是无法预知的,(如果将BFS看作一种A*的话,其
    h(n)恒定为0,g(n)表示到起始点的层数)所以A*算法将当n点到end点的直线距离作为h(n)的估值,显然只能无限接近实际最优解。


  • A*算法维护两张表OPEN和CLOSED,OPEN保存所有可探测但是还没有访问的节点,CLOSED保存素有已经访问的节点;启发函数就当前在
    OPEN表中的节点进行排序,按照代价从低到高排列,每次选择代价最小的节点进行访问;当前访问的节点会根据簿记信息更新代价信息,并且将其直接连接的子
    节点访问OPEN表中,最后将当前节点放入CLOSED表;A*算法开始于将start点放入OPEN表,结束于找到end点,或者OPEN表为
    空,CLOSED表已经包含所有可访问节点。

  • 程序实现中g(n)表示在抽象的状态空间中start点到n点的深度,h(n)表示在实际地图中n点所在地图位置到end点地图位置的直线距离,伪代码如下:


 1 function A*(start,goal)
2 closedset := the empty set
3 // closedset存储已经访问过的节点
4 openset := {start}
5 //openset存储已经探测到但还未访问的节点,初始化时放入start点
6 came_from := the empty map
7 //came_from存储最短路径
8
9 g_score[start] := 0
10 //g_score[u]存储当前当u点到start点的最小代价
11 h_score[start] := heuristic_cost_estimate(start, goal)
12 //h_score[u]存储当前u点到goal点的最小代价
13 f_score[start] := g_score[start] + h_score[start]
14 //f_score[u]存储当前u点在整个状态空间中的代价
15
16 while openset is not empty
17 current := the node in openset having the lowest f_score[] value
18 //从当前openset中选取具有最小f_score的节点current
19 if current = goal
20 return reconstruct_path(came_from, came_from[goal])
21 //判定如果是goal点,则结束
22 remove current from openset
23 add current to closedset
24 //判定如果不是goal点,则将current点从openset中移到closedset
25 for each neighbor in neighbor_nodes(current)
26 //遍历current直接相连的节点neighbor
27 //如果neighbor已经处理过一次(在closedset中),则跳过
28 if neighbor in closedset
29 continue
30 tentative_g_score := g_score[current] + dist_between(current,neighbor)
31 //利用当前current点的g_score重新计算neighbor的g_score
32 if neighbor not in openset
33 //如果neighbor是新探测到的节点(没有在openset中),创建新节点
34 add neighbor to openset
35 h_score[neighbor] := heuristic_cost_estimate(neighbor, goal)
36 tentative_is_better := true
37 else if tentative_g_score < g_score[neighbor]
38 //如果neighbor已经探测到,并且当前g_socre[current]有更小的代价
39 tentative_is_better := true
40 else
41 tentative_is_better := false
42 //更新neighbor的代价
43 if tentative_is_better = true
44 came_from[neighbor] := current
45 g_score[neighbor] := tentative_g_score
46 f_score[neighbor] := g_score[neighbor] + h_score[neighbor]
47
48 return failure
49
50 function reconstruct_path(came_from, current_node)
51 if came_from[current_node] is set
52 p := reconstruct_path(came_from, came_from[current_node])
53 return (p + current_node)
54 else
55 return current_node

时间: 2024-10-13 07:33:11

笔试算法题(48):简介 - A*搜索算法(A Star Search Algorithm)的相关文章

笔试算法题(50):简介 - 广度优先 &amp; 深度优先 &amp; 最小生成树算法

广度优先搜索&深度优先搜索(Breadth First Search & Depth First Search) BFS优缺点: 同一层的所有节点都会加入队列,所以耗用大量空间: 仅能非递归实现: 相比DFS较快,空间换时间: 适合广度大的图: 空间复杂度:邻接矩阵O(N^2):邻接表O(N+E): 时间复杂度:O(V+E): DFS优缺点: 无论是系统栈还是用户栈保存的节点数都只是树的深度,所以空间耗用小: 有递归和非递归实现: 由于有大量栈操作(特别是递归实现时候的系统调用),执行速度

笔试算法题(51):简介 - 红黑树(RedBlack Tree)

红黑树(Red-Black Tree) 红黑树是一种BST,但是每个节点上增加一个存储位表示该节点的颜色(R或者B):通过对任何一条从root到leaf的路径上节点着色方式的显示,红黑树确保所有路径的差值不会超过一倍,最终使得BST接近平衡: 红黑树内每个节点包含五个属性:color, key, left, right和p,p表示指向父亲节点的指针:一棵BST需要同时满足下述五个性质才能称作红黑树: 每个节点只能是红色或者黑色节点中的一种: 根节点必须是黑色: 每个叶节点(NULL)必须是黑色:

笔试算法题(47):简介 - B树 &amp; B+树 &amp; B*树

B树(B-Tree) 1970年由R. Bayer和E. Mccreight提出的一种适用于外查找的树,一种由BST推广到多叉查找的平衡查找树,由于磁盘的操作速度远小于存储器的读写速度,所以要求在尽量少 的操作次数内完成CPU分配的任务,B树就按照此原则设计,B树与红黑树的主要区别在于B树节点可以有超过2个子女,从而大大降低树的高度以减少查询时 间: 一棵M阶B树(Balanced Tree of Order M)是一棵平衡的M路搜索树,满足性质: 根节点至少有两个子女: 除根节点和叶子节点外的

笔试算法题(09):查找指定和值的两个数 &amp; 构造BST镜像树

出题:输入一个已经升序排序的数组和一个数字:要求在数组中查找两个数,这两个数的和正好等于输入的那个数字,输出任意一对数字就可以,要求时间复杂度是O(n): 分析:对于升序排序的数组{-i-j-k-m--},只有可能是i+m=j+k(j和k可能是同一个数),所以可以从两边往中间收缩而忽视其他交叉相加的情况: 解题: 1 void FindSumFactor(int *array, int length, int sum) { 2 int left=0, right=length-1; 3 whil

笔试算法题(07):还原后序遍历数组 &amp; 半翻转英文句段

出题:输入一个整数数组,判断该数组是否符合一个二元查找树的后序遍历(给定整数数组,判定其是否满足某二元查找树的后序遍历): 分析:利用后序遍历对应到二元查找树的性质(序列最后一个元素必定是根节点,从左向右第一个比根节点大的元素开始直到根节点之前的所有元素必定在右子树,之前的所有元素必定在左子树): 解题: 1 bool PostOrderCheck(int *array, int i, int j) { 2 /** 3 * 如快速排序一样,解决小子文件 4 * */ 5 if(j-i+1 ==

笔试算法题(24):找出出现次数超过一半的元素 &amp; 二叉树最近公共父节点

出题:数组中有一个数字出现的次数超过了数组长度的一半,请找出这个数字: 分析: 解法1:首先对数组进行排序,时间复杂度为O(NlogN),由于有一个数字出现次数超过了数组的一半,所以如果二分数组的话,划分元素肯定就是这个数字: 解法2:首先创建1/2数组大小的Hash Table(哈希表可以替代排序时间,由于一个数字出现超过了数组的一半,所以不同元素个数肯定不大于数组的一半),空间复杂度O(N),顺序扫描映射数 组元素到Hash Table中并计数,最后顺序扫描Hash Table,计数超过数组

笔试算法题(06):最大连续子数组和 &amp; 二叉树路径和值

出题:预先输入一个整型数组,数组中有正数也有负数:数组中连续一个或者多个整数组成一个子数组,每个子数组有一个和:求所有子数组中和的最大值,要求时间复杂度O(n): 分析: 时间复杂度为线性表明只允许一遍扫描,当然如果最终的最大值为0表明所有元素都是负数,可以用线性时间O(N)查找最大的元素.具体算法策略请见代码和注释: 子数组的起始元素肯定是非负数,如果添加的元素为正数则记录最大和值并且继续添加:如果添加的元素为负数,则判断新的和是否大于0,如果小于0则以下一个元素作为起始元素重新开始,如果大于

笔试算法题(42):线段树(区间树,Interval Tree)

议题:线段树(Interval Tree) 分析: 线段树是一种二叉搜索树,将一个大区间划分成单元区间,每个单元区间对应一个叶子节点:内部节点对应部分区间,如对于一个内部节点[a, b]而言,其左子节点表示的区间为[a, (a+b)/2],其右子节点表示的区间为[1+(a+b)/2, b]: 对于区间长度为N的线段树,由于其单元节点都是[a, a]的叶子节点,所以其叶子节点数为N,并且整棵树为平衡二叉树,所以总节点数为2N-1,树的深度为log(N)+1: 插入操作:将一条线段[a, b]插入到

笔试算法题(20):寻找丑数 &amp; 打印1到N位的所有的数

出题:将只包含2,3,5的因子的数称为丑数(Ugly Number),要求找到前面1500个丑数: 分析: 解法1:依次判断从1开始的每一个整数,2,3,5是因子则整数必须可以被他们其中的一个整除,如果不包含任何其他因子则最终的结果为1: 解法2:小丑数必然是某个大丑数的因子,也就是乘以2,3,或者5之后的值,所以可以利用已经找到的丑数来寻找下一个丑数,使用数组有序保存已经找到的丑 数,并且当前最大丑数值为M:用大于M/2的丑数乘以2得到M1,用大于M/3的丑数乘以3得到M2,用大于M/5的丑数