搜索算法
基本介绍
搜索算法是利用计算机的高性能来有目的地穷举一个问题的部分或所有的可能情况,从而求出问题的解的一种方法。搜索过程实际上是根据初始条件和扩展规则构造一颗解答树并寻找符合目标状态的结点的过程。
所有的搜索算法从其最终的算法实现上来看,都可以划分为两个部分——控制结构和产生系统,而所有的算法的优化和改进主要都是通过修改其控制结构来完成的。
1. 基本搜索算法
1.1 递归与迭代
递归程序设计是编程语言设计中的一种重要的设计方法。它使许多问题简单化,易于求解。递归的特点:函数或过程直接地或间接地调用它自己本身。
所谓迭代,就是在程序中用同一个变量存放每一次推算出的值,每一次循环都执行都执行同一语句,给同一变量赋以新值,即用一个新值代替旧值。
1.2 深度优先搜索和广度优先搜索
深度搜索和广度搜索的控制结构和产生系统很相似,唯一的区别在于对扩展结点选取上。由于其保留了所有的前驱结点,所以在产生后继结点时可以去掉一部分重复的结点,从而提高了搜索效率。
这两种算法每次都扩展一个结点的所有子结点,而不同的是,深度搜索下一次扩展的是本次扩展出来的子结点中的一个,广度搜索扩展的则是本次扩展的结点的兄弟结点。在具体实现上为了提高效率,所以采用了不同的数据结构。
-
深度优先搜索
深度优先搜索(Depth First Search, DFS)属于图算法的一种,其过程简要来说是对每一个可能的分支路径深入到不能再深入为止,而且每个结点只能访问一次。 -
广度优先搜索
广度优先搜索(Breadth First Search, BFS)又称宽度优先搜索,是最简便的图搜索算法之一。其过程是说在搜索过程中,按层次进行搜索,本层的结点在没有处理完毕之前,不能对下一层结点进行处理,即深度越小的结点越先进行处理。
1.3 回溯
回溯算法是一种系统地搜索问题的解的方法。它的基本思想是:从一条路前行,能进则进,不能进则退回来,换一条路再试。回溯法是一种通用的解题方法。
应用回溯算法的时候,首先要明确定义问题的解空间。解空间中至少应该包含问题的一个解。确定了解空间后,回溯法从开始结点出发,以深度优先的方法搜索整个解空间。
对于回溯算法一般可以采用递归方式来实现:
void DFS(int deep)
{
if 已经超过递归的深度
return ;
for 遍历本结点的所有可扩展结点
{
DFS(deep + 1);
}
}
当然回溯算法还可以使用迭代等其他方式来描述。
2. 搜索算法的一些优化
2.1 剪枝函数
对于回溯算法,需要搜索整棵解空间树,剪枝顾名思义,就是通过某种判断,避免一些不必要的遍历过程,剪去解空间树中的一些不必要的枝条,从而缩小整个搜索的规模,通常有两种策略来提高回溯法的搜索效率,一是用约束函数在扩展结点处剪去不满足约束条件的子树,二是用限界函数剪去不能得到最优解的子树。
对于限界函数,一种比较容易的形式是添加一个全局变量来记录当前最优解,而到达结点的时候计算该结点的预期值并与当前最优解比较,如果不好,则回溯。
2.2 双向广度搜索
所谓双向广度搜索,顾名思义指的是搜索沿正向(从初始结点向目标结点方向搜索)和逆向(从目标结点向初始结点方向搜索)两个方向同时进行,当两个方向上的搜索生成同一子结点时完成搜索过程。
运用双向广度搜索理想上可以减少二分之一的搜索量,从而提高搜索效率。
双向广度搜索一般有两种方法,一种是两个方向交替扩展,另一种是选择结点个数比较少的方向先扩展。显然第一种方法比第二种方法容易实现,但是由于第二种方法克服了双向搜索中结点生成速度不平衡的状态,效率比第一种方法高。