讲广度优先搜索.ppt
文本预览下载声明
双向广度优先搜索(DBFS) DBFS算法是对BFS算法的一种扩展。 BFS算法从起始节点以广度优先的顺序不断扩展,直到遇到目的节点 DBFS算法从两个方向以广度优先的顺序同时扩展,一个是从起始节点开始扩展,另一个是从目的节点扩展,直到一个扩展队列中出现另外一个队列中已经扩展的节点,也就相当于两个扩展方向出现了交点,那么可以认为我们找到了一条路径。 比较 DBFS算法相对于BFS算法来说,由于采用了从两个跟开始扩展的方式,搜索树的深度得到了明显的减少,所以在算法的时间复杂度和空间复杂度上都有较大的优势! DBFS的框架(1) 一、主控函数: void solve() { 1. 将起始节点放入队列q1,将目的节点放入队列q2; 2. 当 两个队列都未空时,作如下循环: ????????? 1) 如果队列q1里的未处理节点比q2中的少(即tail[0]-head[0] tail[1]-head[1]),则扩展(expand())队列q1; ????????? 2) 否则扩展(expand())队列q2 (即tail[0]-head[0] = tail[1]-head[1]时); 3. 如果队列q1未空,循环扩展(expand())q1直到为空; 4. 如果队列q2未空,循环扩展(expand())q2直到为空; } DBFS的框架(2) 二、扩展函数 int expand(i) //其中i为队列的编号(表示q0或者q1) { ??????????取队列qi的头结点H; ????????? 对头节点H的每一个相邻节点adj,作如下循环: ??????????????? 1 如果adj已经在队列qi之前的某个位置出现,则 抛弃节点adj; ??????????????? 2 如果adj在队列qi中不存在[函数 isduplicate(i)] ????????????????????? 1) 将adj放入队列qi; ????????????????????? 2)????如果adj 在队列(q(1-i)),也就是另外一个 队列中出现[函数 isintersect()]; ????????????输出 找到路径?; } DBFS的框架(3) 三、判断当前扩展出的节点是否在另外一个队列出现,也就是判断相交的函数: int isintersect(i,j) //i为队列编号,j为当前节点在队列中的指针 { ??????????遍历队列,判断是否存在 } //【线性遍历的时间复杂度为O(N),如果用HashTable优化,时间复杂度可以降到O(1)】 DBFS参考代码 见附件 进一步提高查找效率,采用hash函数优化线性查找 见附件 A*算法 针对八数码问题,提出了人工智能史上很有名的A*算法(启发式搜索算法) 广度优先算法:当目标的深度较深时,产生很多冗余节点,空间消耗很大 有限深度优先算法:在时间或空间复杂度上均没有明显的优势,但如果目标深度较深而且路径选择得当的话,可以较快地得到解答;当问题复杂时时间消耗很多 A*算法:可以消耗较少的空间解决问题,但是由于每次选择均需要寻找估价函数最小的节点,因此当深度增加相应的节点数目增加时,A*算法在时间上并不占优势。然而,A*算法总可以在有限的时间内得到问题的解。 * A*算法的基本思想 A*算法基本上与BFS算法相同,但是在扩展出一结点后,要根据估价函数对待扩展的结点排序,从而保证每次扩展的结点都是估价函数最小的结点。 估价函数: f(n) = g(n) + h(n) 这里f(n)是估价函数,g(n)是起点到终点的最短路径值(也称为最小耗费或最小代价),h(n)是n到目标的最短路经的启发值。 由于这个f‘(n)其实是无法预先知道的,所以实际上使用“不在位”数和当前层数之和 A*算法的基本步骤 建立一个队列,计算初始结点的估价函数f,并将初始结点入队,设置队列头和尾指针。 取出队列头(队列头指针所指)的结点,如果该结点是目标结点,则输出路径,程序结束。否则对结点进行扩展。 检查扩展的新结点是否与队列中的结点重复 若与不能再扩展的结点重复(位于队列头指针之前),则将它抛弃; 若新结点与待扩展的结点重复(位于队列头指针之后),则比较两个结点的估价函数中g的大小,保留较小g值的结点。跳至第五步。 如果扩展出的新结点与队列中的结点不重复,则按照它的估价函数f大小将它插入队列中的头结点后待扩展结点的适当位置,使它们按从小到大的顺序排列,最后更新队列尾指针 如果队列头的结点还可以扩展,直接返回第二步。否则将队列头指针指向下一结点,再返回第二步。 #include iostream using
显示全部