DFS入门

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中还可以进行剪枝等优化操作,且听下次分享。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值