广告
返回顶部
首页 > 资讯 > 前端开发 > JavaScript >JavaScript遍历实现DFS算法和BFS算法
  • 803
分享到

JavaScript遍历实现DFS算法和BFS算法

摘要

目录DFS(Depth first search)BFS(Breadth first search)总结DFS(Depth first search) Depth first sea

DFS(Depth first search)

Depth first search 称作「深度优先遍历」

下面结合具体例子来理解。如图所示,在一个九宫格图中,绿色位置代表起始位置,红色代表终点位置,灰色区域和宫格图的边界代表此路不通,请从起始位置按照每次只能移动一格的方法移动到终点位置。

我们用 DFS 的方法去解这道题,由图可知,我们可以走上下左右四个方向,我们不妨先约定 “左>上>右>下” 的顺序走,即,如果左边可以走,我们先走左边。然后「递归」下去,没达到终点,我们再原路返回,等又返回到这个位置时,左边已经走过了,那么我们就走上面,按照这样的顺序走。并且我们把走过的路(方向)作标记表示“不能走回头路”。

按照约定,我们先从起点首先向左走到位置 2,这时发现左边不能走了,这时我们就考虑往上走,发现也不能走,同理,下边也不能走。右边刚才已经走过了也不能走,这时候无路可走了,代表这条路不能通往终点,所以现在「无路可走」的时候,沿着原路返回,直到回到了还有未走过的路的路口,尝试继续走没有走过的路径。

于是我们只有回到最初的位置 1,然后判断左边刚才已经走过了并且证实这个方向行不通,那就不必走了,上和右也是不通,所以我们走下边。于是走到了 6 的位置,此时还是按照约定“左>上>右>下” 的顺序走,左边和右边依然不通,上边刚才已经走过了,所以得继续往下走。

继续往下那就是位置 9 了,到了这个路口我们继续按照约定“左>上>右>下” 的顺序,先往左发现可以走,那么就继续走到位置 8,到了位置 8 还是按照刚才的思路继续往左,发现还可以走,并且最终到达终点位置 7。

综上所述,这个过程就是「深度优先遍历」。

DFS 的重点在于状态回溯,因此我们作个思路总结:

  • 深度优先遍历 只要前面有可以走的路,就会一直向前走,直到无路可走才会回头;
  • 「无路可走」有两种情况:① 遇到了墙;② 遇到了已经走过的路;
  • 在「无路可走」的时候,沿着原路返回,直到回到了还有未走过的路的路口,尝试继续走没有走过的路径;
  • 有一些路径没有走到,这是因为找到了出口,程序就停止了;
  • 「深度优先遍历」也叫「深度优先搜索」,遍历是行为的描述,搜索是目的(用途);
  • 遍历不是很深奥的事情,把所有可能的情况都看一遍,才能说「找到了目标元素」或者「没找到目标元素」。遍历也称为穷举,穷举的思想在人类看来虽然很不起眼,但借助计算机强大的计算能力,穷举可以帮助我们解决很多专业领域知识不能解决的问题。

使用 DFS 来解答刚才题目的代码如下:

//我们以红点位置为坐标{0,0},绿色位置坐标为{2,2}
//目标的坐标位置
let target = {
  x: 0,
  y: 0
};
//绿色起点的坐标位置
let currentLocation = {
  x: 2,
  y: 2
};
let used = []; //用来标记地图上哪些点是走过的
let reached = false; //是否能到达目标位置
// 表示灰色区域的格子
const illegalLocation = [
  { x: 0, y: 2 }, //序号1的坐标
  { x: 0, y: 1 }, //序号4的坐标
  { x: 1, y: 1 } //序号5的坐标
];

function isLegalLocation({ x, y }, illegalLocation) {
  let flag = true;
  //位置不能在地图坐标之外
  if (x < 0 || x > 2 || y < 0 || y > 2) {
    return (flag = false);
  }
  //不能走的路径
  for (const { x: locX, y: locY } of illegalLocation) {
    if (x === locX && y === locY) {
      flag = false;
    }
  }
  return flag;
}

//向左移动
function toLeft({ x, y }) {
  return { x: x - 1, y };
}

//向上移动
function toTop({ x, y }) {
  return { x, y: y + 1 };
}

//向右移动
function toRight({ x, y }) {
  return { x: x + 1, y };
}

//向下移动
function toBottom({ x, y }) {
  return { x, y: y - 1 };
}

function dfs(target, location, illegalLocation, used) {
  // 如果当前位置与目标坐标相同表示可以抵达
  if (Object.entries(target).toString() === Object.entries(location).toString()) {
    console.log('reached', location);
    return (reached = true);
  }
  let current = location;
  const newIllegalLocation = illegalLocation.concat(used);
  //假设按照“左>上>右>下”的顺序走
  if (isLegalLocation(toLeft(location), newIllegalLocation)) {
    current = toLeft(location);
  } else if (isLegalLocation(toTop(location), newIllegalLocation)) {
    current = toTop(location);
  } else if (isLegalLocation(toRight(location), newIllegalLocation)) {
    current = toRight(location);
  } else if (isLegalLocation(toBottom(location), newIllegalLocation)) {
    current = toBottom(location);
  } else {
     //走不通了就直接返回
    return false
  }
  used.push(current); //将刚才走过的格子标记为已走过
  return dfs(target, current, illegalLocation, used); //递归下去
}

dfs(target, currentLocation, illegalLocation, used);

BFS(Breadth first search)

Breadth first search 称作「广度优先遍历」

BFS 较之 DFS 之不同在于,BFS 旨在面临一个路口时,把所有的岔路口都记下来,然后选择其中一个进入,然后将它的分路情况记录下来,然后再返回来进入另外一个岔路,并重复这样的操作,用图形来表示则是这样的:

从绿色起点出发,记录所有的岔路口,并标记为走一步可以到达的。然后选择其中一个方向走进去,我们走绿色左边(序号为 2)的那个格子,然后将这个路口可走的方向记录下来并标记为 2,意味走两步可以到达的地方。

接下来,我们回到起点下面 1 的方块上(序号为 6),并将它能走的方向也记录下来,同样标记为 2,因为也是走两步便可到达的地方。这样走一步以及走两步可以到达的地方都搜索完毕了,后续同理,我们可以把走三步的格子给标记出来。

再之后是第四步。我们便成功寻找到了路径,并且把所有可行的路径都求出来了。

注意:格子序号分别为 1、4、5 的地方是灰色区域表示此路不通。

使用 BFS 来解答刚才题目的代码如下:

//我们以红点位置为坐标{0,0},绿色位置坐标为{2,2}
//目标的坐标位置
let target = {
  x: 0,
  y: 0
};
//绿色起点的坐标位置
let currentLocation = {
  x: 2,
  y: 2
};
// 表示灰色区域的格子
const illegalLocation = [
  { x: 0, y: 2 }, //序号1的坐标
  { x: 0, y: 1 }, //序号4的坐标
  { x: 1, y: 1 } //序号5的坐标
];

function isLegalLocation({ x, y }, illegalLocation) {
  let flag = true;
  //位置不能在地图坐标之外
  if (x < 0 || x > 2 || y < 0 || y > 2) {
    return (flag = false);
  }
  //不能走的路径
  for (const { x: locX, y: locY } of illegalLocation) {
    if (x === locX && y === locY) {
      flag = false;
    }
  }
  return flag;
}

//向左移动
function toLeft({ x, y }) {
  return { x: x - 1, y };
}

//向上移动
function toTop({ x, y }) {
  return { x, y: y + 1 };
}

//向右移动
function toRight({ x, y }) {
  return { x: x + 1, y };
}

//向下移动
function toBottom({ x, y }) {
  return { x, y: y - 1 };
}

function bfs(target, location, illegalLocation) {
  let reached = false; //是否能到达目标位置
  let stack = [];  
  let searched = new Set(); //已经走过的格子
  stack.push(location);
  while (stack.length) {
    let temp = stack.pop();
    const newIllegalLocation = illegalLocation.concat([...searched]);
    //假设按照“左>上>右>下”的顺序走
    if (isLegalLocation(toLeft(temp), newIllegalLocation)) {
      temp = toLeft(temp);
    } else if (isLegalLocation(toTop(temp), newIllegalLocation)) {
      temp = toTop(temp);
    } else if (isLegalLocation(toRight(temp), newIllegalLocation)) {
      temp = toRight(temp);
    } else if (isLegalLocation(toBottom(temp), newIllegalLocation)) {
      temp = toBottom(temp);
    } else {
      //没有通路就直接返回
      return false
    }
    searched.add(temp);
    stack.push(temp);
    for (const { x: locX, y: locY } of searched) {
      if (target.x === locX && target.y === locY) {
        //如果当前位置与目标坐标相同表示可以抵达
        reached = true;
        console.log('reached: ', reached);
        stack = [];
        break;
      }
    }
  }
  return reached;
}
bfs(target, currentLocation, illegalLocation);

「广度优先遍历」的思想在生活中随处可见:

  • 如果我们要找一个律师,我们会先在朋友中查找,如果没有找到,继续在朋友的朋友中查找,直到找到为止。
  • 把一块石头投入平静的水面,激起的一层一层波纹就呈现「广度优先遍历」的特点。

总结

  • 「一条路走到底,不撞南墙不回头」是对 DFS 的最直观描述。因此 DFS 可以借助「递归」实现。
  • BFS 呈现出「一层一层向外扩张」的特点,先看到的节点先遍历,后看到的节点后遍历,因此 BFS 可以借助「队列」实现。(遍历到一个节点时,如果这个节点有左(右)孩子节点,依次将它们加入队列。)
  • DFS 适合目标明确的寻找,而 BFS 适合大范围的寻找。

到此这篇关于javascript遍历实现DFS算法和BFS算法的文章就介绍到这了,更多相关JavaScript实现DFS BFS内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: JavaScript遍历实现DFS算法和BFS算法

本文链接: https://www.lsjlt.com/news/177728.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • JavaScript遍历实现DFS算法和BFS算法
    目录DFS(Depth first search)BFS(Breadth first search)总结DFS(Depth first search) Depth first sea...
    99+
    2023-01-14
    JavaScript实现DFS BFS JavaScript DFS BFS JavaScript DFS算法 JavaScript BFS算法
  • C++实现图的遍历算法(DFS,BFS)的示例代码
    目录图的定义图的相关术语图的创建(邻接矩阵)---结构体图的创建(邻接矩阵)---邻接矩阵的创建图的创建(邻接表)---结构体图的创建(邻接表)---邻接表的创建对邻接矩阵进行深度优...
    99+
    2022-11-13
  • Java算法之BFS,DFS,动态规划和贪心算法的实现
    目录前言广度优先搜索深度优先搜索动态规划贪心总结前言 广度优先搜索(BFS)和深度优先搜索(DFS)是图遍历算法中最常见的两种算法,主要用于解决搜索和遍历问题。动态规划和贪心算法则用...
    99+
    2023-05-14
    Java BFS Java DFS Java动态规划 Java贪心
  • Java算法之BFS,DFS,动态规划和贪心算法如何实现
    本篇内容主要讲解“Java算法之BFS,DFS,动态规划和贪心算法如何实现”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java算法之BFS,DFS,动态规划和贪心算法如何实现”吧!广度优先搜索...
    99+
    2023-07-05
  • Java实现深度优先搜索(DFS)和广度优先搜索(BFS)算法
    目录一.深度优先遍历和广度优先遍历1.深度优先遍历2.广度优先遍历二.图像渲染1.题目描述2.问题分析3代码实现1.广度优先遍历2.深度优先遍历三.岛屿的最大面积1.题目描述2.问题...
    99+
    2023-05-18
    Java深度优先和广度优先 Java深度优先 Java广度优先
  • JavaScript二叉树及遍历算法实例分析
    这篇“JavaScript二叉树及遍历算法实例分析”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看...
    99+
    2022-10-19
  • Python 算法基础篇:深度优先搜索( DFS )和广度优先搜索( BFS )
    Python 算法基础篇:深度优先搜索( DFS )和广度优先搜索( BFS ) 引言 1. 深度优先搜索( DFS )算法概述2. 深度优先搜索( DFS )算法实现实例1:图的 DFS 遍...
    99+
    2023-10-04
    深度优先 算法 python 广度优先
  • JavaScript中深度优先遍历和广度优先遍历算法的示例分析
    这篇文章主要为大家展示了“JavaScript中深度优先遍历和广度优先遍历算法的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“JavaScript中深度...
    99+
    2022-10-19
  • JavaScript二叉树及各种遍历算法详情
    目录什么是二叉树满二叉树完全二叉树二叉树的存储数组存储链表存储与二叉树相关的算法深度优先遍历广度优先遍历先序遍历中序遍历后序遍历前言: 上一篇文章中介绍了树的概念、深度优先遍历和广度...
    99+
    2022-11-13
  • 怎么理解Java优先遍历和广度优先遍历算法
    这篇文章主要讲解了“怎么理解Java优先遍历和广度优先遍历算法”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么理解Java优先遍历和广度优先遍历算法”吧!深度优先遍历主要思路是从图中一个未...
    99+
    2023-06-16
  • Java实现深度搜索DFS算法详解
    目录DFS概述解释思路案例题-单身的蒙蒙题目描述题解整体代码DFS概述 深度优先搜索是一种在开发爬虫早期使用较多的方法。它的目的是要达到被搜索结构的叶结点(即那些不包含任何超链的HT...
    99+
    2022-11-12
  • C++实现二叉树非递归遍历算法详解
    目录一、二叉树的前序遍历二、二叉树的中序遍历三、二叉树的后序遍历3.1 方法一3.2 方法二一、二叉树的前序遍历 题目链接 我们可以把任何一棵树看成左路节点,左路节点和右子树。先访问...
    99+
    2023-05-17
    C++二叉树非递归遍历 C++非递归遍历 C++二叉树遍历
  • C#中怎么实现一个二叉树遍历算法
    这篇文章给大家介绍C#中怎么实现一个二叉树遍历算法,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。C#算法实现了二叉树的定义,怎么构造一颗已知的二叉树,用几种常规的算法(先序,中序,后序,层次)进行C#二叉树遍历。希望能...
    99+
    2023-06-18
  • 利用JS实现二叉树遍历算法实例代码
    目录前言 一、二叉树 1.1、遍历二叉树 1.2、用js表示二叉树 1.3、前序遍历算法 1.4、中序遍历算法 1.5、后序遍历算法 1.6、按层遍历算法 二、算法题 1.1、二叉树...
    99+
    2022-11-12
  • C++ DFS算法实现走迷宫自动寻路
    C++ DFS算法实现走迷宫自动寻路,供大家参考,具体内容如下 深度优先搜索百度百科解释: 事实上,深度优先搜索属于图算法的一种,英文缩写为DFS即Depth First Searc...
    99+
    2022-11-12
  • Python Prim算法通过遍历墙实现迷宫的生成
    之前,我们在另外一篇文章中使用Prim算法生成了一个完美迷宫,利用的是遍历网格的方法,这一次,我们要教教大家用遍历墙的方法生成,上一篇文章链接:Python利用Prim算法生成迷宫 ...
    99+
    2023-01-06
    Python Prim生成迷宫 Python生成迷宫 Python Prim算法
  • 如何实现数据结构中的二叉树遍历算法
    今天就跟大家聊聊有关如何实现数据结构中的二叉树遍历算法,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。今天咱们来看一种新...
    99+
    2022-10-19
  • 怎么使用Vue计算属性中reduce方法实现遍历
    今天小编给大家分享一下怎么使用Vue计算属性中reduce方法实现遍历的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。vue计...
    99+
    2023-07-05
  • python的序列遍历和字典遍历的实现方法
    这篇文章主要介绍“python的序列遍历和字典遍历的实现方法”,在日常操作中,相信很多人在python的序列遍历和字典遍历的实现方法问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解...
    99+
    2022-10-18
  • C++ DFS算法如何实现走迷宫自动寻路
    小编给大家分享一下C++ DFS算法如何实现走迷宫自动寻路,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!C++ DFS算法实现走迷宫自动寻路,供大家参考,具体内容...
    99+
    2023-06-15
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作