DFS和BFS的比较
DFS(Depth First Search,深度优先搜索)和BFS(Breadth First Search,广度优先搜索)是两种典型的搜索算法。下面通过一个实例来比较一下深度优先搜索和广度优先搜索的搜索过程。
【例1】马的行走路径
设有一个n*m的棋盘(2<=n<=50,2<=m<=50),在棋盘上任一点有一个中国象棋马,如图1(a)所示。马行走的规则为:(1)马走日字;(2)马只能向右走,即如图1(b)所示的4种走法。
编写一个程序,输入n和m,找出一条马从棋盘左下角(1,1)到右上角(n,m)的路径。例如:输入n=4、m=4时,输出路径 (1,1)->(2,3)->(4,4)。这一路经如图1(c)所示。若不存在路径,则输出"No!"
(1)编程思路。
将棋盘的横坐标规定为i,纵坐标规定为j,对于一个n×m的棋盘,i的值从1到n,j的值从1到m。棋盘上的任意点都可以用坐标(i,j)表示。
马有四种移动方向,每种移动方法用偏移值来表示,将这些偏移值分别保存在数组dx和dy中,可定义数组int dx[4]={1,1,2,2}和int dy[4]={-2,2,-1,1}。
定义数组int visit[51][51]标记某位置马儿是否已走过,初始时visit数组的所有元素值均为0,visit[i][j]=0表示坐标(i,j)处马儿未走过。同时为了后面输出路径方便,在标记visit[i][j]的值时,可以将其设置为其前一个位置的信息,例如visit[i][j] = x*100+y,它表示马儿由坐标(x,y)走到坐标(i,j)处。
(2)采用深度优先搜索编写的源程序。
#include <iostream>
using namespace std;
#define N 51
struct Node
{
int x;
int y;
};
int main()
{
int n,m;
int dx[4]={1,1,2,2};
int dy[4]={-2,2,-1,1};
int visit[N][N]={0};
Node s[N*N],cur,next; // s为栈
int top,i,x,y,t; // top为栈顶指针
cin>>n>>m;
top=-1; // 栈S初始化
cur.x=1; cur.y=1;
visit[1][1]=-1; // 点(1,1)为出发点,无前驱结点
s[++top]=cur; // 初始结点入栈;
bool flag= false; // 置搜索成功标志flag为假
while(top>=0 && !flag) // 栈不为空
{
cur=s[top--]; // 栈顶元素出栈
if (cur.x==n && cur.y==m)
{
flag=true;
x=n; y=m;
while (visit[x][y]!=-1)
{
cout<<"("<<x<<","<<y<<") <-- ";
t=visit[x][y];
x=t/100;
y=t%100;
}
cout<<"(1,1)"<<endl;
break;
}
for (i=0;i<4;i++)
{
x=cur.x+dx[i]; y=cur.y+dy[i];
if(x >=1 && x<=n && y>=0 && y<=m && visit[x][y]==0)
{
visit[x][y] = (cur.x)*100+cur.y; // 映射保存前驱结点信息
next.x=x; next.y=y; // 由cur扩展出新结点next
s[++top]=next; // next结点入栈
}
}
}
if (!flag)
cout<<"No path!"<<endl;
return 0;
}
为理解深度优先搜索的结点访问顺序,可以在上面源程序中的出栈语句后加上一条语句
cout<<"("<<cur.x<<","<<cur.y<<") -- "; 输出结点的出栈访问顺序。
(3)DFS的搜索过程。
以输入5,5为例,用树形结构表示马可能走的所有过程(如下图),求从起点到终点的路径,实际上就是从根结点开始搜索这棵树。
马从(1,1)开始,按深度优先搜索法,扩展出两个结点(2,3)和(3,2)依次入栈,之后(3,2)出栈,即走一步到达(3,2),判断是否到达终点,若没有,则继续往前走,扩展出结点(4,4)、(5,1)、(5,3)依次入栈,再走一步到达(5,3),没有到达终点,继续往前走,(5,3)的下一步所走的位置不在棋盘上,则另选一条路径再走;(5,1)出栈,即走到(5,1);…,直到到达(5,5),搜索过程结束。
以输入5,5为例,输出的深度优先访问顺序为:
(1,1) -- (3,2) -- (5,3) -- (5,1) -- (4,4) -- (5,2) -- (2,3) -- (4,2) -- (5,4) -- (3,5) -- (4,3) -- (5,5)。
(4)采用广度优先搜索编写的源程序。
#include <iostream>
using namespace std;
#define N 51
struct Node
{
int x;
int y;
};
int main()
{
int n,m;
int dx[4]={1,1,2,2};
int dy[4]={-2,2,-1,1};
int visit[N][N]={0};
Node q[N*N],cur,next; // q为队列
int front,rear,i,x,y,t; // front为队头指针,rear队尾指针
cin>>n>>m;
front=rear=0; // 队列q初始化
cur.x=1; cur.y=1;
visit[1][1]=-1; // 点(1,1)为出发点,无前驱结点
q[rear++]=cur; // 初始结点入队
bool flag= false; // 置搜索成功标志flag为假
cout<<"结点访问顺序为:";
while(rear!=front && !flag) // 队列不为空
{
cur=q[front++]; // 队头元素出队
cout<<"("<<cur.x<<","<<cur.y<<") -- ";
if (cur.x==n && cur.y==m)
{
flag=true;
x=n; y=m;
cout<<endl;
cout<<"行走路径为:";
while (visit[x][y]!=-1)
{
cout<<"("<<x<<","<<y<<") <-- ";
t=visit[x][y];
x=t/100;
y=t%100;
}
cout<<"(1,1)"<<endl;
break;
}
for (i=0;i<4;i++)
{
x=cur.x+dx[i]; y=cur.y+dy[i];
if(x >=1 && x<=n && y>=1 && y<=m && visit[x][y]==0)
{
visit[x][y] = (cur.x)*100+cur.y; // 映射保存前驱结点信息
next.x=x; next.y=y; // 由cur扩展出新结点next
q[rear++]=next; // next结点入栈
}
}
}
if (!flag)
cout<<"No path!"<<endl;
return 0;
}
(5)BFS的搜索过程。
结合上面的搜索图,广度优先搜索采用自上而下,从左到右的顺序搜素结点。因此,结点访问顺序为:(1,1) -- (2,3) -- (3,2) -- (3,1) -- (3,5) -- (4,2) -- (4,4) -- (5,1) -- (5,3) -- (4,3) -- (5,2) -- (5,4) -- (5,5)。
DFS和BFS的比较的更多相关文章
- Clone Graph leetcode java(DFS and BFS 基础)
题目: Clone an undirected graph. Each node in the graph contains a label and a list of its neighbors. ...
- 数据结构(12) -- 图的邻接矩阵的DFS和BFS
//////////////////////////////////////////////////////// //图的邻接矩阵的DFS和BFS ////////////////////////// ...
- 数据结构(11) -- 邻接表存储图的DFS和BFS
/////////////////////////////////////////////////////////////// //图的邻接表表示法以及DFS和BFS //////////////// ...
- 在DFS和BFS中一般情况可以不用vis[][]数组标记
开始学dfs 与bfs 时一直喜欢用vis[][]来标记有没有访问过, 现在我觉得没有必要用vis[][]标记了 看代码 用'#'表示墙,'.'表示道路 if(所有情况都满足){ map[i][j]= ...
- 图论中DFS与BFS的区别、用法、详解…
DFS与BFS的区别.用法.详解? 写在最前的三点: 1.所谓图的遍历就是按照某种次序访问图的每一顶点一次仅且一次. 2.实现bfs和dfs都需要解决的一个问题就是如何存储图.一般有两种方法:邻接矩阵 ...
- 图论中DFS与BFS的区别、用法、详解?
DFS与BFS的区别.用法.详解? 写在最前的三点: 1.所谓图的遍历就是按照某种次序访问图的每一顶点一次仅且一次. 2.实现bfs和dfs都需要解决的一个问题就是如何存储图.一般有两种方法:邻接矩阵 ...
- 数据结构基础(21) --DFS与BFS
DFS 从图中某个顶点V0 出发,访问此顶点,然后依次从V0的各个未被访问的邻接点出发深度优先搜索遍历图,直至图中所有和V0有路径相通的顶点都被访问到(使用堆栈). //使用邻接矩阵存储的无向图的深度 ...
- dfs和bfs的区别
详见转载博客:https://www.cnblogs.com/wzl19981116/p/9397203.html 1.dfs(深度优先搜索)是两个搜索中先理解并使用的,其实就是暴力把所有的路径都搜索 ...
- 邻接矩阵实现图的存储,DFS,BFS遍历
图的遍历一般由两者方式:深度优先搜索(DFS),广度优先搜索(BFS),深度优先就是先访问完最深层次的数据元素,而BFS其实就是层次遍历,每一层每一层的遍历. 1.深度优先搜索(DFS) 我一贯习惯有 ...
- 判断图连通的三种方法——dfs,bfs,并查集
Description 如果无向图G每对顶点v和w都有从v到w的路径,那么称无向图G是连通的.现在给定一张无向图,判断它是否是连通的. Input 第一行有2个整数n和m(0 < n,m < ...
随机推荐
- C++安全异常std:auto_ptr
auto_ptr它是C++标准库(<utility>)为了一个智能指针类模板来解决资源泄漏所提供的问题(注意:这只是一个简单的智能指针) auto_ptr在事实原则的实现RAII,对资源的 ...
- 峰识别 峰面积计算 peak detection peak area 源代码 下载
原文:峰识别 峰面积计算 peak detection peak area 源代码 下载 Comparative analysis of peak-detection techniques ...
- SEO分享:为什么我的资源外链这么多的高品质?
在小浪前制成的制品" [完整版]我怎么3的月800单词索引厨师主页!".之后,很多人都表示了极大的钦佩观看.顽强的运行力,真SEO它是运行顽强的力量.也有人说是吹牛吧,一天500外 ...
- linux_无秘登录问题(不生效)
1 . 登录1,执行命令 ssh-keygen -t rsa 之后一路回 车,查看刚生成的无密码钥对: cd .ssh 后 执行 ll 2 .把 id_rsa.pub 追加到授权的 key 里面去. ...
- hdu 4035 可能性DP 成都网络游戏
http://acm.hdu.edu.cn/showproblem.php?pid=4035 获得: 1.首先推断是不是树.事实上,所有的感觉身影,既看边数==算-1是不成立 2.有时候,我告诉孩子来 ...
- .net中模拟键盘和鼠标操作
原文:.net中模拟键盘和鼠标操作 周银辉 其实SendKeys类提供的方法蛮好用的,可惜的是WPF中不能用了,说是WPF的消息循环方式改成了Dispatcher,所以直接调用System.Windo ...
- 运行control userpasswords2实现winXP自动登录
原文:运行control userpasswords2实现winXP自动登录 如果你的计算机只是自己一人在用,且每次都用同一个用户名(或者你根本没在意过什么是用户名),而每次都要输入密码,是否太麻烦了 ...
- SQL Server 2008收缩日志文件--dbcc shrinkfile参数说明
原文:SQL Server 2008收缩日志文件--dbcc shrinkfile参数说明 DBCC SHRINKFILE 收缩相关数据库的指定数据文件或日志文件大小. 语法 DBCC SHRINKF ...
- 微信小程序把玩(三十七)location API
原文:微信小程序把玩(三十七)location API location API也就分这里分两种wx.getLocation(object)获取当前位置和wx.openLocation(object) ...
- JVM的几个介绍
关于jvm内存的几点 jvm在运行时分为方法区(Method Area) .虚拟机栈(VM Stack).本地方法栈(Native Method Stack).堆 (Heap).程序计数器 (Prog ...