最近在看一些算法书,查缺补漏,什么?OJ?表示只做过几十个水题,现在开始正式看算法,希望早日脱离鱼塘。
本博文面向数据结构已经入门的人
引用《啊哈!算法》
从前上课的时候只知道深搜是用来搜图和二叉树的,现在才知道原来深搜的应用如此灵活
1.输入一个数n,输入1~n的全排列
比如123 132 213 231 312 321
先上代码
#include "stdafx.h"
#include <cstdio>
#include "iostream"
using namespace std;
typedef struct Node
{
int num=0;
bool outHand = false;
}Node;
int n;
Node list[10];
void DFS(int step)
{
if (step == n+1) //判断边界,此时所有数都放到了容器中
{
for (int i = 1;i <= n;i++)
cout << list[i].num; //输出容器中的状态
cout << endl;return; //返回到堆栈中上一个递归状态
}
for (int i = 1;i <= n;i++)//尝试每一种可能
{
if (list[i].outHand == false)//前提是这个n还没有放进去
{
list[step].num = i; //把1到n放到容器list中
list[i].outHand = true; //改变状态
DFS(step + 1); //继续递归下一步
list[i].outHand= false;//下一步完事后,肯定是要换一个数的,所以我们把之前的数收回去
}
}
return;//所有可能都完事的时候,返回。
}
void main()
{
cin >> n;
DFS(1);
}
系统会对每一次递归的函数进行一次进堆栈操作,return即是返回到上一次调用的函数那里,也就是递归的上一次函数的状态。
也就是栈帧。
说个简单的情况,比如n=3 也就是三个位置ABC(隐含一个D,D为空)
第一次走到A,在A上尝试每一种可能,先把1放上去,到B,执行for循环,1已经放过了,循环到2,把2放上去,到C,把3放上去。再调用DFS(step+1),也就是到D,此时满足边界条件,输出容器状态,1,2,3,return到上一个递归状态,也就是到走到C时,此时DFS(step+1)执行完毕,开始执行list[3].outHand=false;for循环完毕,return;返回到走到B时的状态,此时DFS(step+1)执行完毕,开始执行list[2].outHand=false;也就是说此时,2和3都拿到了手中,然后for循环走到i=3,把3放到B中,执行DFS(step+1),走到C,在C中尝试每一种可能,因为1在A,3在B,所以2在C,再走到D,到达边界,输出132,返回,后面213 231情况类似,都是递归。
这就是深度优先遍历的一个简单的小程序。
这个程序在递归深度比较大的时候,算法效率会变得非常的低,所以我们可以自己定义一个栈来模拟递归时函数进入系统堆栈的情况,不过这个问题后面再提
2.例题1的变种,寻找满足ABC+DEF=GHI的情况有多少
比如173+286=459
看到这个题,我想大部分新手第一反应就是暴力循环,把所有可能的数字情况1到9全部枚举一遍,满足情况就输出,嗯,九重循环O(n^9)
尝试下深