1. 概述:
搜索算法是利用计算机的性能优势来有目的的枚举一个问题解空间的部分或所有的可能情况,从而求出问题的解的一种方法。在问题求解过程中,人们所面临的大多数现实问题往往没有确定性的算法,需要通过搜索算法来解决。
搜索问题一般只需要考虑两个基本问题:
1、使用合适的状态空间来表示问题。
2、测试该状态空间中目标状态是否会出现
一个问题的基本信息由4部分组成
1、初始状态集合—–>定义了问题的初始状态
2、操作符集合—–>把一个问题从一个状态转换到另一个状态的动作集合
3、目标检测函数—->用来确定一个状态是不是目标
4、路径费用函数—->对每条路径赋予一定费用的函数
其中,初始状态集合和操作符集合定义了问题的搜索空间
搜索算法的两个重要问题
搜索什么和在哪里搜索
因此搜索可以被分为两个阶段:状态空间的生成阶段和在该状态空间中对所求问题的状态的搜索
搜索可以分为启发式搜索和盲目搜索
2. 盲目搜索:
一般是指从当前状态到目标状态需要走多少步或者每条路径的花费并不知道,按照预定的搜索策略进行搜索,终止于目标状态,由于这种状态没有考虑到问题本身的特性,具有很大的盲目性,效率不高。需要提高盲目搜索的效率就需要寻找合理的搜索策略,该边搜索顺序
常用的盲目搜索有:深度优先搜搜(DFS)、广度优先搜索(BFS)
1、深度优先搜索DFS
深度优先搜索沿着树的深度遍历树的节点,尽可能深的搜索树的分支
当节点v的所有边都已经被搜索过,将回溯到发现节点v的那条边的起始节点
这一过程一直进行到已发现从源节点可达的所有节点为止。
如果还存在未被发现的节点,则选择其中一个作为源节点并重复上述过程
是一种典型的盲目搜索,如果不进行优化,DFS效率很低,一般要根据题意进行剪枝
DFS实现时一般用到递归,使用系统堆栈
void DFS(int v)
{
visit(v);
visited[i] = true;
if (v和u存在边 && !visited[u])
{
DFS(u);
}
}
2、广度优先搜索BFS
是从任意节点V开始,一次搜索其可以扩展的每一个节点V1,V2。。。
当一层节点全部搜索完之后,再依次搜索第一个可扩展节点的所有节点
知道所有节点均被访问,算法终止。
BFS和树的层序遍历很像,搜索顺序具有明显的层次性,一般用队列实现
注意:先访问顶点,再把顶点入队,访问完该顶点的所有邻接顶点时,再出第一次访问的节点,接下来就是重复上述步骤
void BFS(int v)
{
int w;
visit(v); //访问顶点
visited[v] = true; //顶点V对应的访问标记置为1
queue.push_back(v); //入队
while (!queue.Empty())
{
v = queue.pop_back(); //退出队首元素
w = firstAdj(v); //求v的第一个邻接点,无邻接点时返回-1
while (w != -1)
{
if (!visited[w]) //没有访问过该节点
{
visit(w); //访问该节点
queue.push_back(w); //入队
visited[w] = true; //标记置为1
}
w = nextAdj(v); //求下一个邻接点,无邻接点时返回-1
}
}
}
BFS常用于解决最优可行解的问题,类似最小步数、最短步数等
3. 启发式搜索:
是在搜索过程中加入了与问题有关的启发式信息,用于指导搜索朝着最有希望的方向进行,扫除不必要的搜索过程,加速问题求解并得到最优解。
由于启发式信息根据问题不同而异,因此需要分析问题的条件,寻找可以改变搜索顺序和剪枝的条件