博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
DFS BFS相关流程与代码
阅读量:6642 次
发布时间:2019-06-25

本文共 5624 字,大约阅读时间需要 18 分钟。

本文以一个走迷宫为例子,其中1表示墙壁,0表示可以走的路,只能上下左右走,不能斜着走,要求找到左上角到右下角的线路。

 0,1,0,0,0,

 0,1,0,1,0,
 0,0,0,0,0,
 0,1,1,1,0,
 0,0,0,1,0,

如上图所示是一个5X5的迷宫。

 

dfs可以使用堆栈实现,也可以使用递归的方式实现。利用堆栈的形式伪代码如下:

DFS:

将起点标记为已走过的点,并压栈;

while(栈不为空)

{

  从栈顶弹出一个点P;

  if(p是终点)

    break;

  否则沿上下左右四个方向探索

  if(和P相邻的点有路可走,并且没有走过)

    将相邻的点标记为已走过点,并且将改点压栈,改点的前驱就是P点

}

if (P是终点)

{

  打印P店的坐标;

  while(p有前驱)

  {

    P = P 的前驱;

    打印P坐标;

  }

else

  没有路线走出迷宫

 

BFS则是使用队列的方式实现,能够找到最短的路径

将起点标记为已走过的点,并入队列;

while(队列不为空)

{

  出队列一个点P;

  if(p是终点)

    break;

  否则沿上下左右四个方向探索

  if(和P相邻的点有路可走,并且没有走过)

    将相邻的点标记为已走过点,并且将改点入队列,该点的前驱就是P点

}

if (P是终点)

{

  打印P店的坐标;

  while(p有前驱)

  {

    P = P 的前驱;

    打印P坐标;

  }

else

  没有路线走出迷宫

 

#include 
#define MAX_ROW 5#define MAX_COL 5struct point{ int row; int col;}stack[512];int top = 0;void push(struct point p){ stack[top++] = p;}struct point pop(void){ return stack[--top];}int is_empty(void){ return top == 0;}int maze[MAX_ROW][MAX_ROW] = { 0,1,0,0,0, 0,1,0,1,0, 0,0,0,0,0, 0,1,1,1,0, 0,0,0,1,0,};void print_maze(void){ int i,j; for(i = 0; i < MAX_ROW; i++) { for(j = 0; j < MAX_COL; j++) printf("%d ", maze[i][j]); printf("\n"); }  printf("********************\n"); }struct point predecessor[MAX_ROW][MAX_COL] = { {
{
-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1}}, {
{
-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1}}, {
{
-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1}}, {
{
-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1}}, {
{
-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1}},};void visit(int row, int col, struct point pre){ struct point visit_point = {row, col}; maze[row][col] = 2; predecessor[row][col] = pre; push(visit_point);}int main(void){ struct point p = {
0,0}; maze[p.row][p.col] = 2; push(p); while( ! is_empty() ) { p = pop(); if (p.row == MAX_ROW - 1 && p.col == MAX_COL - 1) break; if(p.col + 1 < MAX_COL && 0 == maze[p.row][p.col+1]) visit(p.row, p.col+1, p); if(p.row + 1 < MAX_ROW && 0 == maze[p.row+1][p.col]) visit(p.row+1, p.col, p); if(p.col - 1 >= 0 && 0 == maze[p.row][p.col-1]) visit(p.row, p.col-1, p); if(p.row - 1 >= 0 && 0 == maze[p.row-1][p.col]) visit(p.row-1, p.col, p); print_maze(); } if (p.row == MAX_ROW - 1 && p.col == MAX_COL - 1) { printf("(%d,%d)\n", p.row, p.col); while(predecessor[p.row][p.col].row != -1) { p = predecessor[p.row][p.col]; printf("(%d,%d)\n", p.row, p.col); } } else { printf("No path!\n"); } return 0;}

 上述代码是使用堆栈的方法实现DFS走迷宫的,入口是左上角,出口右下角。其中打印走迷宫的步骤是逆向打印。

值得注意的是,如果其中找到的终点不break;则可以找到所有的走出迷宫的走路路径。

那么问题来了,能输出所有的路径,那么有什么意义呢?

请看下面的一道题:走迷宫捡宝石,走哪条路捡到的最多。

问题描述如下:

一个迷宫里,0代表路,1代表墙,2代表地上有宝石。不能走重复的路线,如何走出去并同时捡到最多的宝石?

核心部分代码,这次采用的递归的方式实现,道理和堆栈式一样的。

主函数中2句核心代码就是:

jewels_count = 0;

traverse(0, 0,0);

jewels_count = 0;traverse(0, 0,0);void traverse(int x, int y, int count){    int i, j, nTemp;    if (maze[x][y]==2) {        count++;    }    nTemp = maze[x][y];    maze[x][y]=3;    if (x==N-1 && y==N-1){         if (count>jewels_count){            jewels_count=count;            for(i=0;i
= 1)&& (maze[x][y-1]==0 || maze[x][y-1]==2)) traverse(x, y-1, count); if ((x >= 1)&& (maze[x-1][y]==0 || maze[x-1][y]==2)) traverse(x-1, y, count); maze[x][y]=nTemp;}

 

这个代码的关键部分,就是最后一句 maze[x][y] = nTemp; 用于回溯。 这部分代码使用堆栈本人没能写出来。

 

下面的是BFS的代码,同样,打印走的路径也是逆向打印的。

#include 
#define MAX_ROW 5#define MAX_COL 5struct point{ int row; int col; int predecessor;}queue[512];int head = 0;int tail = 0;void enqueue(struct point p){ queue[tail++] = p;}struct point dequeue(void){ return queue[head++];}int is_empty(void){ return head == tail;}int maze[MAX_ROW][MAX_ROW] = { 0,1,0,0,0, 0,1,0,1,0, 0,0,0,0,0, 0,1,1,1,0, 0,0,0,1,0,};void print_maze(void){ int i,j; for(i = 0; i < MAX_ROW; i++) { for(j = 0; j < MAX_COL; j++) printf("%d ", maze[i][j]); printf("\n"); } printf("**************\n");}struct point predecessor[MAX_ROW][MAX_COL] = { {
{
-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1}}, {
{
-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1}}, {
{
-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1}}, {
{
-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1}}, {
{
-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1}},};void visit(int row, int col){ struct point visit_point = {row, col, head-1}; maze[row][col] = 2; enqueue(visit_point);}int main(void){ struct point p = {
0, 0, -1}; maze[p.row][p.col] = 2; enqueue(p); while( ! is_empty() ) { p = dequeue(); if (p.row == MAX_ROW - 1 && p.col == MAX_COL - 1) break; if(p.col + 1 < MAX_COL && 0 == maze[p.row][p.col+1]) visit(p.row, p.col+1); if(p.row + 1 < MAX_ROW && 0 == maze[p.row+1][p.col]) visit(p.row+1, p.col); if(p.col - 1 >= 0 && 0 == maze[p.row][p.col-1]) visit(p.row, p.col-1); if(p.row - 1 >= 0 && 0 == maze[p.row-1][p.col]) visit(p.row-1, p.col); print_maze(); } if (p.row == MAX_ROW - 1 && p.col == MAX_COL - 1) { printf("(%d,%d)\n", p.row, p.col); while(p.predecessor != -1) { p = queue[p.predecessor]; printf("(%d,%d)\n", p.row, p.col); } } else { printf("No path!\n"); } return 0;}

如果我们采用BFS的方法来实现查找捡宝石最多的路径,该如何做?

难点:广度优先搜索采用队列的形式,如何回溯?遗憾本人不会,也不知能否这样实现。

转载于:https://www.cnblogs.com/chenxf0619/p/4293328.html

你可能感兴趣的文章
程序员的出路0
查看>>
关于Unity中UI中的RawImage节点以及制作地图滚动效果
查看>>
HiWorkV1.3版震撼公布,今日起正式公开測试!
查看>>
(七)Thymeleaf的 th:* 属性之—— th: ->设值& 遍历迭代& 条件判断
查看>>
linux 线程切换效率与进程切换效率相差究竟有多大?
查看>>
Tensorflow一些常用基本概念与函数
查看>>
2014中国民营企业500强在京津冀经济区、珠江三角洲、长江三角洲分布
查看>>
【JEECG技术博文】JEECG 简单实例解说权限控制
查看>>
如果想从jenkins直接生成docker镜像,并推送到harbor中,最简单的脚本如何实现?...
查看>>
条件随机场CRF(二) 前向后向算法评估标记序列概率
查看>>
codecombat之边远地区的森林1-11关及地牢38关代码分享
查看>>
小米2S电池电量用尽充电无法开机解决方法
查看>>
确定性这剂毒药,你喝过没
查看>>
GODOT 3.0 开发进度汇报 #6
查看>>
c#简单写售票系统
查看>>
简单RPC框架-业务线程池
查看>>
Swift iOS tableView static cell动态计算高度
查看>>
POJ - 3164 Command Network(朱刘算法)
查看>>
phalcon:官方多模块支models层,mode数据库配置
查看>>
Java并发编程:Callable、Future和FutureTask
查看>>