浅谈BFS和DFS

您所在的位置:网站首页 DFS和BFS算法序列例题 浅谈BFS和DFS

浅谈BFS和DFS

#浅谈BFS和DFS | 来源: 网络整理| 查看: 265

深度优先遍历(Depth First Search, 简称DFS)与广度优先遍历(Breath First Search,简称BFS)是图论中两种非常重要的算法,生产上广泛用于拓扑排序,寻路(走迷宫)、搜索引擎、爬虫等。

DFS 与 BFS 对比

DFS (Deep First Search)

DFS:从当前节点开始,先标记当前节点,再寻找与当前节点相邻,且未标记过的节点( 这是一个递归思想的DFS)

当前节点不存在下一个节点,则返回前一个节点进行DFS 当前节点存在下一个节点,则从下一个节点进行DFS

DFS 遍历使用递归遍历:

1234567void dfs(TreeNode root){ if (root == null){ return ; } dfs(root.left); dfs(root.right);}

只是比较两段代码的话,最直观的感受就是:DFS 遍历的代码比 BFS 简洁太多了!这是因为递归的方式隐含地使用了系统的 栈,我们不需要自己维护一个数据结构。如果只是简单地将二叉树遍历一遍,那么 DFS 显然是更方便的选择。

网格结构中的 DFS

网格问题的基本概念

我们首先明确一下岛屿问题中的网格结构是如何定义的,以方便我们后面的讨论。

网格问题是由 个小方格组成一个网格,每个小方格与其上下左右四个方格认为是相邻的,要在这样的网格上进行某种搜索。

岛屿问题是一类典型的网格问题。每个格子中的数字可能是 0 或者 1。我们把数字为 0 的格子看成海洋格子,数字为 1 的格子看成陆地格子,这样相邻的陆地格子就连接成一个岛屿。

image-20201107204300931

在这样一个设定下,就出现了各种岛屿问题的变种,包括岛屿的数量、面积、周长等。不过这些问题,基本都可以用 DFS 遍历来解决。

DFS 的基本结构

网格结构要比二叉树结构稍微复杂一些,它其实是一种简化版的图结构。要写好网格上的 DFS 遍历,我们首先要理解二叉树上的 DFS 遍历方法,再类比写出网格结构上的 DFS 遍历。我们写的二叉树 DFS 遍历一般是这样的:

123456789void travese(TreeNode root){ //判断 base case if (root == null){ return ; } //访问两个相邻节点:左子节点,右子节点 travese(root.left); travese(root.right);}

可以看到,二叉树的DFS有两个要素:【访问相邻节点】 和 【判断base case】。

第一个要素是访问相邻的节点。二叉树的相邻节点非常简单,只有左子树和右子树。二叉树本身就是一个递归定义的结构:一颗二叉树,他的左子树和右子树也是一颗二叉树。那么我们的DFS遍历只需要调用左子树和右子树即可。

第二个要素就是判断base case。一般来说,二叉树遍历的base case是 root == null。这样一个条件判断其实有两个含义:

表示root指向指向的子树为空,不需要再往下遍历了。 在root == null的时候及时返回,可以让后面的root.left 和root.right操作不会出现空指针异常

对于网格上的DFS,可以参考二叉树的DFS,写出网格的DFS的两个要素:

相邻节点对于格子 (r, c) 来说(r 和 c 分别代表行坐标和列坐标),四个相邻的格子分别是 (r-1, c)、(r+1, c)、(r, c-1)、(r, c+1)。换句话说,网格结构是「四叉」的。

image-20201107204116039

其次,网格 DFS 中的 base case 是什么?从二叉树的 base case 对应过来,应该是网格中不需要继续遍历、grid[r][c] 会出现数组下标越界异常的格子,也就是那些超出网格范围的格子。

image-20201107204315074

DFS遍历网格的框架代码123456789101112131415161718192021222324252627// 避免重复遍历将已经遍历的格子设置为2// 0 —— 海洋格子// 1 —— 陆地格子(未遍历过)// 2 —— 陆地格子(已遍历过)void dfs(int[][],grid int r, int c){ //判断base case if (!inArea(grid, r, c)){ return; } //如果格子不是岛屿,直接返回 if (grid[r][c] != 1){ return; } grid[r][c] = 2; //将已经遍历过得格子 变为2 //访问上、下、左、右相邻节点、 dfs(grid, r - 1, c); dfs(grid, r + 1, c); dfs(grid, r, c - 1); dfs(grid, r, c + 1);}//判断坐标(r,c)是否在网格中boolean inArea(int[][] grid, int r, int c){ return


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3