搜索常见的有深度优先搜索(DFS)和宽度优先搜索(BFS);
深度优先搜索(DFS)
深度优先搜索就是先从一个状态出发,然后不停的转移状态,根据不同的需求进行不同情况的状态转移,重复步骤得到结果,直至访问完所有的节点;
上图的序号就是搜索顺序;
回溯法(探索与回溯法)是一种选优搜索法,又称为试探法,按选优条件向前搜索,以达到目标。也就是说,每次遇到不符合条件的节点时就往后退,重新选择;
伪代码
int op()//编辑一个判断是否合乎题目条件的函数,由其返回值得知是否满足
{
if(条件)
return 1;
else
return 0;
}
void dfs(开始的点)
{
{
判断边界
}
{
op()
是否满足条件;
dfs(开始点+1);
初始化;
}
}
同样以上图为例,如果用上回溯的时候,就会多了判断条件这一步,假如现在我要判断在这七个节点中有没有相加起来等于k的情况,那么就有了一个判断条件,那么此时从根节点出发(每一层就相当于判断一个数的取与不取),判断要不要根节点的数,如果要就是向那根支下面继续搜索;直到满足题意,或者找到底都没找到满足条件的情况;
例子
比如说全排列的例子:
//全排列问题
#include<stdio.h>
#include<string.h>
int n;
char a[15];
char re[15];
int vis[15];
//假设有n个字符要排列,把他们依次放到n个箱子中
//先要检查箱子是否为空,手中还有什么字符,把他们放进并标记。
//放完一次要恢复初始状态,当到n+1个箱子时,一次排列已经结束
void dfs(int step)
{
int i;
if(step==n+1)//判断边界
{
for(i=1;i<=n;i++)
printf("%c",re[i]);
printf("\n");
return ;
}
for(i=1;i<=n;i++)//遍历每一种情况
{
if(vis[i]==0)//check满足
{
re[step]=a[i];
vis[i]=1;//标记
dfs(step+1);//继续搜索
vis[i]=0;//恢复初始状态
}
}
return ;
}
int main(void)
{
int T;
scanf("%d",&T);
getchar();
while(T--)
{
memset(a,0,sizeof(a));
memset(vis,0,sizeof(vis));//对存数据的数组分别初始化
scanf("%s",a+1);
n=strlen(a+1);
dfs(1);//从第一个箱子开始
}
return 0;
}
广度搜索(BFS)
如果说深度搜索是一条路走到黑,不撞南墙不回头,那么广度搜索就是很保险的探险方法,先找自己离的最近的数,找完之后,再找离根节点远一点点的数,一直到答案浮出水面,所以说,这个搜索比较适合找最短距离;
就是一层一层找;
如果要实现具体的问题,那么可以举一个例子;
找上图中从黑色五角星到红色五角星的最短距离;
那么首先第一步就是这样的:
然后就是按步骤搜索,直到有一条路线通向红色五角星;
总结
用冒险来形容这俩种搜索,深度搜索就是一条路走到黑,加上回溯就是听劝,肯回头判断走的这一步是不是对的,不对就一直退;广度搜索就是地毯式搜索,以根节点为中心,慢慢搜索;