第三章 搜索
一. 一些搜索的概念
-
边缘(开节点表): 所有待扩展的叶节点的集合
-
CLOSE表: 用来记录已经拓展过的结点
-
算法的性能评估
-
完备性: 如果问题有解,能找到解
-
最优性: 找到的解是最优的
-
时间复杂度
-
空间复杂度
-
时间空间复杂度的度量:
-
时间由搜索过程中产生的结点数目来度量
-
空间由内存中存储的最多结点数量来度量
-
通常小于状态空间数量|V|+|E|
-
-
-
-
分支因子: 一个结点可以扩展出多少个子结点,即树的分支数量
搜索树

搜索图

注意
树搜索:重复状态增大时间开销,甚至导致死循环
图搜索:避免重复状态,空间开销大
二. 无信息搜索
1. BFS
BFS的最主要的是要解决空间上的问题,O(bd)的复杂度。空间为O(bm)
2. 一致代价(Djakarta)算法
f(n) = g(n)
每次选取f(n)最大或者最小的进行拓展(采用优先队列,记录节点)
如果一致代价存在代价为0的行动就会陷入死循环。
如果每一步的代价大于等于0,那么一致代价算法具有完备性
时间复杂度O(b(1+lowbound(C/e))
空间复杂度O(b1+lowbound(C/e))
3. DFS
4. 深度受限的搜索(不是一个具体的搜索算法)
假定深度为l的结点没有后继结点
当深度到达某个值后就不再深入搜索。这就相当于在一个高度为h的树上使用深度优先算法
时间复杂度O(bm)
空间复杂度O(bm)
5. 迭代加深的深度优先算法
这个算法是调用上面的深度受限搜索(从深度为0到最大深度d,)
算法模拟
深度不断增加。对于每个深度都是采用的深度优先算法。该算法如果解再最后一层出现那么搜索过程就十分庞大。
迭代加深的广度优先毫无意义,因为广度优先搜索本来就是深度不断增加。没必要通过限制搜索的深度。
性能分析
对于深度为d,分支数为b的情况,
-
深度受限的搜索算法产生的结点数为:
N(DLS)= b0 + b1+…+ bd
-
迭代加深的深度优先算法产生的结点数为:
N(IDS)=(d+1)+(d)b+(d-1)*b2+….+(1)bd
第一层有一个节点,但是生成了(d+1)次
第二层有b个节点,生成了(d)次
第三层有b2个,生成(d-1)
. . .
-
当 b = 10, d = 5,
N(DLS)= 1 + 10 + 100 + 1,000 + 10,000 + 100,000 = 111,111
N(IDS)= 6 + 50 + 400 + 3,000 + 20,000 + 100,000 = 123,456
时间复杂度O(bm)
空间复杂度O(bm)
6. 双向搜索
无信息搜索性能
三. 启发式搜索
启发式搜索主要是依靠启发函数f(n) = g(n) + h(n)
进行拓展。兼顾了过去状态又考虑了未来状态
- f(n) : 评估当前节点的价值
- g(n) : 起点到当前节点的价值
- h(n) : 当前节点到大目标的预估值
1. 贪婪最佳优先算法(GBS)
f(n) = h(n)
每次选取最接近目标的节点进行拓展 (采用优先队列,记录节点)
贪婪算法的设计目的就是想要从当前节点扩展离目标节点最近的一个节点。这个算法只用到了最简单的启发式函数f(n)=h(n),在罗马尼亚问题中,使用的是当前地点到目的地的直线距离(这个信息不能由问题本身的描述计算得到,而且这个信息是有用的——因为和实际路程相关,所以是一个有用的启发式),在此问题中,GBS搜索代价最小,但是不是最优。
为什么一致代价算法可以得到最优值而贪婪最优却不行
因为一致代价算法选取的启发函数是f(n) = g(n)
,是起点到当前节点的实际值
而一致代价算法选取的启发函数是f(n) = h(n
),是起点到当前节点的预估值
预估值存在误差,而实际值不存在
- 复杂度:
- 时间 O(bm)
- 空间O(bm)
2. A*算法
结合了一致代价算法和贪婪最优算法。A*算法既是完备的也是最优的
f(n) = g(n) + h(n)
作为评估函数,采用优先队列来扩展f(n)最大或者最小的节点,直到搜索的需要的结果。
一致的启发式都是可采纳的
A*算法最优性的证明


启发式搜索性能分析

松弛问题


e-20211114160804112" style=“zoom:67%;” />
