DFS即深度优先搜索,算法思想简单描述就是不撞南墙不回头,找到搜索条件,返回结果,停止搜索,反之,如果遇到边界值,返回上一节点,搜索另一条链,直到找到结果为止。如果说BFS操作像队列,那么DFS就是栈,个人感觉如果找最短,BFS会高效一点,如果找存不存在,则DFS会高效一点。关于DFS和BFS的一系列比较和解释,大家可以点击进入下面的网址,我觉得这篇文章写的非常好,生动形象,易于接受http://t.csdn.cn/zdCqH
DFS的
伪代码如下:
void dfs( ){
if(){ //条件满足,找到结果
//执行操作;
return ;
}
for( ){
//当层要做的事情
//标记已访问
dfs(step+1);
//回溯
}
return ;
}
显而易见,代码段非常简洁,貌似还没有开始就已经结束了,其实越是简洁的代码,越难理解。当然了,伪代码终究是为了便于理解算法,它在日后的做题中也会发生千变万化。那么咱就来一个经典例题,借助例题来分析此算法。
题目描述
我们称n的全排列1,2,3...,n按照一定顺序组成的序列
比如3的所有全排列为:
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
现在请你生成n的所有全排列
输入格式
第一行一个整数n
输出格式
输出所有n的全排列,按字典序从小到大输出。
字典序比较大小方法为从第一个数字开始比较,若不同则比较出来大小,否则接着比较第二位,直到比较出来大小位置。样例中就是按照字典序排序后的结果。
输入样例
3
输出样例
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
代码:
#include <bits/stdc++.h>
using namespace std;
int n;
int num[10],vis[10];//num数组即存储输出数据,
//vis数组为了防止数据重复使用
void dfs(int step){
if(step==n+1){ //循环结束判定条件,输出数据
for(int i=1;i<=n;i++)
printf("%d ",num[i]);
printf("\n");
return;
}
for(int i=1;i<=n;i++){
if(vis[i]==0){ //如果未被使用,进行赋值,标记
num[step]=i;
vis[i]=1;
dfs(step+1); //完事进入下一个位置的数据读取
vis[i]=0;//回溯,重难点
}
}
}
int main()
{
while(cin>>n){
memset(vis,0,sizeof(vis));
dfs(1);
}
return 0;
}
代码很简洁,但是难倒不少人,这道题如果借助二叉树,递归图更好,那么将会变得容易许多。
下面是我列出的递归图,再结合代码意思,这类题应该可以理解,至于在以后的做题,那就取决于经验和熟练度了
DFS中递归结束之后返回是返回上次被调用的地方,而非直接返回到主函数部分,并且,最后的回溯绊倒了不少人,很多人会忘了,假如没有这个回溯,那么输出的将是1——n
算法基础和对算法的理解就到这儿,DFS中还可以进行剪枝等优化操作,且听下次分享。