您的位置:首页 > 其它

【bfs与dfs】基础

2017-08-04 23:14 246 查看
bfs : 广度优先搜索,一层一层搜索. 属于一种盲目搜寻法,目的是系统地展开并检查图中的所有节点,以找寻结果。换句话说,它并不考虑结果的可能位置,彻底地搜索整张图,直到找到结果为止。广度优先的基本思想是,从顶点v0出发,访问与v0相邻的点,访问结束后,再从这些点出发,继续访问,直到访问结束为止。标记被访问过的点同深搜一下,不过,广度优先一般需要用到队列。

dfs : 深度优先搜索。深度优先的基本思想简单说就是搜到底,重新搜。从v0为起点进行搜索,如果被访问过,则做一个标记,直到与v0想连通的点都被访问一遍,如果这时,仍然有点没被访问,可以从中选一个顶点,进行再一次的搜索,重复上述过程,所以深度优先的过程也是递归的过程。

DFS 和 BFS使用哪种跟具体的数据(源点和目标的位置)有关,比如你数据结构是树,要搜索根节点到某一叶子节点的路径。这时候,如果这个叶子节点距离根节点比较远,使用深度优先DFS效率最高。如果这个叶子节点距离根节点比较近,使用广度优先BFS效率更高。你可以自己画一个树,自己用脑子模拟一下这两个算法,一下子就明白了。

找到了两篇有图解的可以去看一看:bfs:http://blog.csdn.net/raphealguo/article/details/7523411

dfs:http://rapheal.iteye.com/blog/1526863

以下是两种的代码,也附有注释,:

广搜dfs:

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stack>
#include <queue>
#include <vector>
#include <algorithm>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
int map[5][5];//地图
int go[4][2]= {{1,0},{-1,0},{0,-1},{0,1}};//四个方向
int pre[10000];//用来寻找父亲节点
bool vis[10][10];//标记数组
struct node
{
int x,y,s;
};//存储坐标信息及当前步数
int bfs(int x,int y)
{
node now,to;//先在的和将要走的
now.x=x,now.y=y,now.s=0;
queue<node>q;//创建队列
vis[x][y]=1;//走过的标记为1
q.push(now);//加入队首
while(!q.empty())
{
now=q.front();
if(now.x==4&&now.y==4)      return now.s;//满足条件时返回走过的步数
q.pop();
for(int i=0; i<4; i++)
{
int xx=now.x+go[i][0];
int yy=now.y+go[i][1];
if(xx>=0&&yy>=0&&xx<5&&yy<5&&map[xx][yy]==0&&vis[xx][yy]==0)//判断是否越界
{
vis[xx][yy]=1;//标记走过的
to.x=xx,to.y=yy,to.s=now.s+1;
pre[xx*5+yy]=now.x*5+now.y;//存储坐标,转化成一维形式
q.push(to);
}
}
}
return 0;
}
void myprint(int n)
{
//printf("pre[%d]=(%d)\n",n,pre
);
if(n==pre
)return;
myprint(pre
);//寻找父亲节点
printf("(%d, %d)\n",n/5,n%5);
}//回溯打印路径
int main()
{
mem(vis,0);
for(int i=0; i<5; i++)
for(int j=0; j<5; j++)
scanf("%d",&map[i][j]);//读入地图
if(bfs(0,0))
{
printf("(0, 0)\n");//先打印0 0
myprint(4*5+4);//从(4,4)开始回溯
}
else
printf("-1\n");
return 0;
}


深搜dfs:

/*
深搜dfs
*/
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stack>
#include <queue>
#include <vector>
#include <algorithm>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
int map[10][10],min1;
struct node
{
int x,y;
};//存坐标

stack<node> s1;//用栈来存储路径
node ans[100];//存储反过来后路径
void mycopy(stack<node> a)//栈是反着来的,用这个倒过来
{
for(int i=(int)a.size()-1; i>=0; i--)
{
ans[i]=a.top();
a.pop();
}
}
int go[4][2]= {{1,0},{-1,0},{0,1},{0,-1}};//四个方向
bool vis[10][10];//标记数组
void dfs(int x,int y,int step)
{
node now;
now.x=x,now.y=y;
s1.push(now);//把坐标存进栈中
if(x==4&&y==4)//当搜索到终点时
{
if(step<min1)
{
min1=step;//更新最小的步数
mycopy(s1);//翻转栈中的路径
}

}

for(int i=0; i<4; i++)
{
int xx=x+go[i][0],yy=y+go[i][1];
if(xx>=0&&xx<5&&yy>=0&&yy<5&&map[xx][yy]==0&&vis[xx][yy]==0)//判断是否越界
{
vis[xx][yy]=1;//走过的标记为1
dfs(xx,yy,step+1);//搜索下一层
vis[xx][yy]=0;//标记回来,以便下次搜索
}
}
s1.pop();//坐标出栈
}
int main()
{
for(int i=0; i<5; i++)
for(int j=0; j<5; j++)
scanf("%d",&map[i][j]);
mem(vis,0);//初始化标记数组
min1=999;
while(s1.size()) s1.pop();//清空栈
dfs(0,0,0);
if(min1==999)
printf("-1\n");
else
{
//printf("%d\n",min1);
for(int i=0; i<=min1; i++)
printf("(%d, %d)\n",ans[i].x,ans[i].y);//输出结果
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  bfs dfs 搜索