当前位置:   article > 正文

【算法】DFS深度优先搜索:递归实现_dfs递归实现

dfs递归实现

一.DFS

    1.介绍

       DFS(Depth-First-Search)不同于BFS广度优先搜索,它更加侧重于对树/图进行深度搜索,在搜索时,从根节点开始一直往下到没有节点可以搜索为止,在搜索过程中可将路径进行保存。实现DFS深度优先搜索可借用“栈”来实现,递归或者非递归的方法均可,在解决迷宫问题时,在寻找迷宫出口问题上使用DFS是个合适的选择。

    2.图解

                       

       如图上所示,灰色部分为墙壁,如果想从“起点”位置到达“终点”,使用DFS时,会将所有“可能”的路径都走一遍,直到无路可走仍未发现终点时,将退回至最近一次分叉路口从另一条路继续往下寻找,直到找到终点位置。

                       

       第一次向左走至尽头,没有发现终点,则回到“起点”处,开始往下寻找。

                        

       当走到“黑色箭头”标记处时,发现该节点为“分叉点”,故DFS记录这个位置,选择一条路径开始往下寻找。

                        

      往下走到尽头后发现找不到尽头,故退回到“分叉点”,开始往右边寻找。

                       

      向右走又出现了分叉点,故DFS记录这个位置,选择一条路径开始往上寻找。

                        

      走到尽头后发现没有到终点所以回到最近一次“分叉点”进行往下寻找。

                        

      找到终点,结束。

二.递归寻找迷宫出口

    1.问题描述

      DFS最经典的问题之一,寻找迷宫中起点到终点的路径:{{0, 0, 1, 0, 1}, 
                                                                                                 {0, 1, 1, 1, 0},
                                                                                                 {0, 0, 0, 0, 0},
                                                                                                 {0, 1, 1, 1, 0},
                                                                                                 {0, 0, 0, 1, 0}};

     2.代码源码

       2.1.记录二维网格坐标位置、是否为墙壁、是否走过等状态

  1. struct Node
  2. {
  3. int _x;
  4. int _y;
  5. int _value;
  6. bool _IsWall;
  7. bool _IsWalked;
  8. };
  9. vector<std::vector<Node>> Push_Node(std::vector<std::vector<int>>& push_into)
  10. {
  11. std::vector<std::vector<Node>> push;
  12. int state;
  13. for (int i = 0; i < push_into.size(); i++)
  14. {
  15. std::vector<Node> into;
  16. for (int j = 0; j < push_into[i].size(); j++)
  17. {
  18. if (push_into[i][j] == 1)
  19. state = true;
  20. else
  21. state = false;
  22. Node node{ i,j,push_into[i][j],state,false };
  23. into.push_back(node);
  24. }
  25. push.push_back(into);
  26. }
  27. return push;
  28. }

       2.2.寻找指定节点的相邻节点,详细代码可参考我之前写过的文章:【C/C++】获取二维数组相邻八个/四个方向的数据

  1. std::vector<Node> Find_Beighbors(int x, int y, std::vector<std::vector<Node>>& vec)
  2. {
  3. int max_x = (vec.size() - 1);
  4. int max_y = ((vec[x].size()) - 1);
  5. std::vector<Node> list; //扩列存储相邻元素
  6. for (int dx = (x > 0 ? -1 : 0); dx <= (x < max_x ? 1 : 0); ++dx)
  7. {
  8. for (int dy = (y > 0 ? -1 : 0); dy <= (y < max_y ? 1 : 0); ++dy)
  9. {
  10. if ((dx == 0 || dy == 0) && (dx + dy != 0))
  11. {
  12. list.push_back(vec[x + dx][y + dy]);
  13. }
  14. }
  15. }
  16. return list;
  17. }

        2.3.核心部分,使用递归进行DFS搜索,递归使用的是系统的栈,简称隐式栈

  1. bool DFS(Node root, Node target, vector<vector<Node>>& push_into) //递归调用,隐形栈
  2. {
  3. if (root._x == target._x && root._y == target._y)
  4. return true;
  5. push_into[root._x][root._y]._IsWalked = true;
  6. vector<Node> Beighbors = Find_Beighbors(root._x, root._y, push_into);
  7. for (int i = 0; i < Beighbors.size(); i++)
  8. {
  9. if (!push_into[Beighbors[i]._x][Beighbors[i]._y]._IsWall)
  10. {
  11. if (!push_into[Beighbors[i]._x][Beighbors[i]._y]._IsWalked)
  12. {
  13. push_into[Beighbors[i]._x][Beighbors[i]._y]._IsWalked = true;
  14. if (DFS(push_into[Beighbors[i]._x][Beighbors[i]._y], target, push_into))
  15. {
  16. push_into[Beighbors[i]._x][Beighbors[i]._y]._value = 3; //标记路径
  17. printf("(%d,%d)\n",push_into[Beighbors[i]._x][Beighbors[i]._y]._x, push_into[Beighbors[i]._x][Beighbors[i]._y]._y);
  18. return true;
  19. }
  20. }
  21. }
  22. }
  23. return false;
  24. }

      3.实际使用情况

            起始节点坐标:(0,0),目标节点坐标:(4,4),输出为:

             

           起始节点坐标:(0,0),目标节点坐标:(4,2),输出为:

             

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/388226
推荐阅读
相关标签
  

闽ICP备14008679号