【算法】图论中DFS和BFS模板讲解

图论的解题模板和二叉树基本一致,都是在DFS和BFS基础上进行求解。

二叉树的DFS和BFS模板如下所示:

复制代码
public void DFSTree(TreeNode root){
  if(root==null)
      return null;
  DFSTree(root.left);
  DFSTree(root.right);
}

public void BFSTree(TreeNode root){
  if(root==null) return;
  Deque<TreeNode> queue=new ArrayDeque<>();
  queue.offer(root);
  while(!queue.isEmpty()){
      TreeNode curNode=queue.poll();
      if(curNode.left!=null){
          queue.offer(curNode.left);
      }
      if(curNode.right!=null){
          queue.offer(curNode.right);
      }
  }
}

根据二叉树的DFS和BFS模板可以发现,整代码有两个要素:访问相邻结点和判断base case。

由于二叉树本身是一个递归的定义,一颗二叉树它的左右子树也是一颗二叉树,因此访问相邻结点只需访问左右结点即可。

而对DFS来说,base case就是root==null,这有两层含义:一是递归的终止条件,表示当前root指向的结点为空,要停止递归,不需要再往下遍历了。二是root==null表示遍历到了叶子结点,应及时返回,避免出现root.leftroot.right空指针异常。而对BFS来说,base case就是while(!queue.isEmpty())curNode.left!=nullcurNode.right!=nullwhile(!queue.isEmpty())表示当前队列不为空,即还需要继续遍历,而curNode.left!=nullcurNode.right!=null则保证入队的元素均不为空。

类比二叉树的特性,可以写出图中DFS和BFS的两个要素:1、图中某个格子的相邻结点是什么?该如何访问?2、判断base case。

对于格子(row,col)来说,它的相邻结点分别在上下左右,分别为(row-1,col)、(row+1,col)、(row,col-1)、(row,col+1),其次类比二叉树通过root==null来充当base case确保不需要继续遍历,那么在图中的base case应该就是出现数组越界的格子,这样就能得到图论中DFS和BFS的基础架构

复制代码
public void DFSGrid(int[][] grid,int row,int col){
    // 判断 base case
    if(row<0||col<0||row>=grid.length||col>=grid[0].length)
      return;
    // 访问上、下、左、右四个相邻结点
    DFSGrid(grid,row-1,col);
    DFSGrid(grid,row+1,col);
    DFSGrid(grid,row,col-1);
    DFSGrid(grid,row,col+1);
}

public void BFSGrid(int[][] grid,int row,int col){
  Deque<int[]> queue=new ArrayDeque<>();
  queue.offer(new int[]{row,col});
  //处理当前格子等操作
  grid[row][col]=已遍历
  while(!queue.isEmpty()){
      int[] cur=queue.poll();
      row=cur[0];
      col=cur[1];
      //判断base case
      if(row>=0&&col>=0&&row<grid.length&&col<grid[0].length){
      //记录当前格子等操作
      grid[row][col]=已遍历
      // 访问上、下、左、右四个相邻结点
      queue.offer(new int[]{row-1,col});
      queue.offer(new int[]{row+1,col});
      queue.offer(new int[]{row,col-1});
      queue.offer(new int[]{row,col+1});
      }
  }
}

在不熟悉的情况下,可能会疑惑为什么DFS(grid,row,col)和queue.offer(grid,new int[]{row-1,col})时不用判断参数是否合法?难度不会数组越界吗?其实可以先合法性判断,然后再进行DFS和BFS,但是我们用的方法是先使用后判断,将判断的操作统一放在前面,这样在取上下左右四个位置的时候不用判断四次参数的合理性,而是先将其视为合法的进行保存,然后在要访问的时候在统一判断合法性,避免了多次冗余的判断。

其次对于BFS的queue中为什么要存坐标,是因为通过坐标可以直接访问到对应的格子,同时更改坐标可以快速定位到其上下左右四个格子,若存储格子,那如何传递参数来访问上下左右四个格子呢?

相关推荐
6Hzlia3 小时前
【Hot 100 刷题计划】 LeetCode 739. 每日温度 | C++ 逆序单调栈
c++·算法·leetcode
良木生香4 小时前
【C++初阶】:STL——String从入门到应用完全指南(1)
c语言·开发语言·数据结构·c++·算法
XWalnut4 小时前
LeetCode刷题 day16
数据结构·算法·leetcode·链表·动态规划
foundbug9996 小时前
基于混合整数规划的电池容量优化 - MATLAB实现
数据结构·算法·matlab
memcpy07 小时前
LeetCode 2452. 距离字典两次编辑以内的单词【暴力;字典树】中等
算法·leetcode·职场和发展
王老师青少年编程7 小时前
csp信奥赛C++高频考点专项训练之贪心算法 --【排序贪心】:魔法
c++·算法·贪心·csp·信奥赛·排序贪心·魔法
wearegogog1237 小时前
基于和差波束法的单脉冲测角MATLAB实现
人工智能·算法·matlab
AI科技星8 小时前
灵魂商数(SQ) · 全域数学统一定义【乖乖数学】
算法·机器学习·数学建模·数据挖掘·量子计算
晓觉儿8 小时前
【GPLT】2026年第十一届团队程序设计天梯赛赛后题解(已写2h,存档中)
数据结构·c++·算法·深度优先·图论