当前位置:   article > 正文

图的遍历—深度优先搜索(DFS)_图的深度优先遍历代码

图的深度优先遍历代码

一.定义

一条路走到尽头,往回一步,再一条路走到尽头,往回一步...直到达到终点。

步骤归纳:

  1. 访问起始节点v;

  1. 如果v的第一个邻接点没有访问过。深度遍历此邻接点;

  1. 如果当前的邻接点已经访问过了,再重新遍历v的第2个邻接点;

  1. 如果所有邻接点都已经访问过了,就返回上一个访问的顶点


二.应用--迷宫求解(在网格上的遍历)

题目描述

给出一个N*N的迷宫矩阵示意图,从起点[0,0]出发,寻找路径到达终点[N-1, N-1]。

输入

第一行输入t,表示有t个迷宫

第二行输入n,表示第一个迷宫有n行n列

第三行起,输入迷宫每一行的每个方格的状态,0表示可通过,1表示不可通过

输入n行

以此类推输入下一个迷宫

输出

逐个输出迷宫的路径

如果迷宫不存在路径,则输出no path并回车

如果迷宫存在路径,将路径中每个方格的x和y坐标输出,从起点到终点,每输出四个方格就换行,最终以单词END结尾,具体格式参考示范数据

tips:向右,向下、向左、向上逆时针探索路径。

输入样例

  1. 2
  2. 8
  3. 0 0 0 1 1 1 1 1
  4. 1 0 0 0 1 0 0 1
  5. 1 0 0 0 1 0 0 0
  6. 1 1 0 0 0 0 0 1
  7. 0 0 1 1 0 1 1 0
  8. 0 0 0 0 0 0 1 1
  9. 1 1 1 1 1 0 0 1
  10. 0 0 0 0 1 0 0 0
  11. 7
  12. 0 0 0 1 1 1 1
  13. 1 0 0 1 0 0 1
  14. 1 0 0 1 0 0 0
  15. 1 1 0 0 0 0 1
  16. 0 0 1 1 0 1 0
  17. 1 0 0 0 0 1 0
  18. 0 0 0 0 1 1 0

样例输出

  1. [0,0]--[0,1]--[0,2]--[1,2]--
  2. [1,3]--[2,3]--[3,3]--[3,4]--
  3. [4,4]--[5,4]--[5,5]--[6,5]--
  4. [6,6]--[7,6]--[7,7]--END
  5. no path

参考代码

  1. #include <iostream>
  2. #include <stack>
  3. using namespace std;
  4. //每个点有两个属性:横坐标和纵坐标
  5. class node
  6. {
  7. public:
  8. int x, y;
  9. node(int x1, int y1) { x = x1, y = y1; }
  10. };
  11. int main()
  12. {
  13. int t, n;
  14. cin >> t;
  15. while (t--)
  16. {
  17. stack<node>path, path1; //path作为临时变量,path1输出最后的路径
  18. int a[300][300];
  19. cin >> n;
  20. //输入邻接矩阵
  21. for (int i = 0; i < n; i++)
  22. {
  23. for (int j = 0; j < n; j++)
  24. cin >> a[i][j];
  25. }
  26. //如果迷宫的初始点不能走,则没有路径可走
  27. if (a[0][0] == 1)
  28. {
  29. cout << "no path" << endl;
  30. continue;
  31. }
  32. //初始点可以走
  33. else
  34. {
  35. //将可以走的点信息存储起来
  36. path.push(node(0, 0));
  37. a[0][0] = 1;//将走过的点标记为"1"
  38. int nowx = 0, nowy = 0;//初始化现在的坐标为初始点的坐标
  39. while (1)
  40. {
  41. //注意迷宫的坐标范围是0-n-1,则要判断横纵坐标改变后是否超出迷宫边界
  42. if (a[nowx][nowy + 1] == 0 && nowy + 1 < n)//向右走
  43. {
  44. path.push(node(nowx, nowy + 1));
  45. a[nowx][nowy + 1] = 1;
  46. nowy += 1;
  47. }
  48. else if (a[nowx + 1][nowy] == 0 && nowx + 1 < n)//向下走
  49. {
  50. path.push(node(nowx + 1, nowy));
  51. a[nowx + 1][nowy] = 1;
  52. nowx += 1;
  53. }
  54. else if (a[nowx][nowy - 1] == 0 && nowy - 1 >= 0)//向左走
  55. {
  56. path.push(node(nowx, nowy - 1));
  57. a[nowx][nowy - 1] = 1;
  58. nowy -= 1;
  59. }
  60. else if (a[nowx - 1][nowy] == 0 && nowx - 1 >= 0)//向上走
  61. {
  62. path.push(node(nowx - 1, nowy));
  63. a[nowx - 1][nowy] = 1;
  64. nowx -= 1;
  65. }
  66. //如果一条路走到了尽头,就往回走一步,体现在"pop"出当前结点
  67. else
  68. {
  69. nowx = path.top().x;
  70. nowy = path.top().y;
  71. if (!((a[nowx][nowy + 1] == 0 && nowy + 1 < n) ||
  72. (a[nowx + 1][nowy] == 0 && nowx + 1 < n) ||
  73. (a[nowx][nowy - 1] == 0 && nowy - 1 >= 0) ||
  74. (a[nowx - 1][nowy] == 0 && nowx - 1 >= 0)))
  75. {
  76. path.pop();
  77. }
  78. }
  79. //到达终点就跳出循环,输出路径
  80. if (path.empty() || (nowx == n - 1 && nowy == n - 1)) break;
  81. }
  82. //路径为空,也就是在初始点没有邻接点可以走
  83. if (path.empty())
  84. {
  85. cout << "no path" << endl;
  86. }
  87. //存在路径就输出路径
  88. else
  89. {
  90. while (!path.empty()) { path1.push(path.top()); path.pop(); }
  91. int i = 0; //以下是输出路径的代码
  92. while (!path1.empty())
  93. {
  94. node cpos = path1.top();
  95. if ((++i) % 4 == 0)
  96. cout << '[' << cpos.x << ',' << cpos.y << ']' << "--" << endl;
  97. else
  98. cout << '[' << cpos.x << ',' << cpos.y << ']' << "--";
  99. path1.pop();
  100. }
  101. cout << "END" << endl;
  102. }
  103. }
  104. }
  105. return 0;
  106. }

三.应用--在图上的遍历

题目描述

给出一个图的邻接矩阵,对图进行深度优先搜索,从顶点0开始

注意:图n个顶点编号从0到n-1

输入

第一行输入t,表示有t个测试实例

第二行输入n,表示第1个图有n个结点

第三行起,每行输入邻接矩阵的一行,以此类推输入n行

第i个结点与其他结点如果相连则为1,无连接则为0,数据之间用空格隔开

以此类推输入下一个示例

输出

每行输出一个图的深度优先搜索结果,结点编号之间用空格隔开

输入样例

  1. 2
  2. 4
  3. 0 0 1 1
  4. 0 0 1 1
  5. 1 1 0 1
  6. 1 1 1 0
  7. 5
  8. 0 0 0 1 1
  9. 0 0 1 0 0
  10. 0 1 0 1 1
  11. 1 0 1 0 0
  12. 1 0 1 0 0

样例输出

  1. 0 2 1 3
  2. 0 3 2 1 4

参考代码

  1. #include<iostream>
  2. using namespace std;
  3. const int maxn = 50;//假定图最多包含50个顶点
  4. int g[maxn][maxn];//图的邻接矩阵
  5. int visit[maxn];//访问标志数组,标识每个结点是否已经访问过,1表示访问过,0表示未访问过
  6. int vnum;//结点数量
  7. void DFS(int now)//now表示当前结点
  8. {
  9. cout << now << " ";
  10. visit[now] = 1;
  11. int* a = new int[vnum];//存放与当前结点相连(有边)的结点编号
  12. for (int i = 0; i < vnum; i++)
  13. {
  14. a[i] = -1;
  15. }
  16. int k = 0;
  17. for (int i = 0; i < vnum; i++)
  18. {
  19. if (g[now][i])//编号为i的结点与当前结点相连(有边)
  20. {
  21. a[k++] = i;//存放到数组里
  22. }
  23. }
  24. int i = 0;
  25. for (int w = a[i]; w != -1; w = a[++i])
  26. {
  27. if (!visit[w])
  28. {
  29. DFS(w);
  30. }
  31. }
  32. delete[]a;
  33. }
  34. int main()
  35. {
  36. int t;
  37. cin >> t;
  38. while (t--)
  39. {
  40. cin >> vnum;
  41. for (int i = 0; i < vnum; i++)
  42. visit[i] = 0;
  43. //输入邻接矩阵,1表示结点之间相连,0表示结点之间没有相连
  44. for (int i = 0; i < vnum; i++)
  45. {
  46. for (int j = 0; j < vnum; j++)
  47. cin >> g[i][j];
  48. }
  49. for (int v = 0;v< vnum;v++)
  50. {
  51. //若该顶点未访问,就调用DFS函数进行深度优先搜索
  52. if (!visit[v])
  53. {
  54. DFS(v);
  55. }
  56. }
  57. cout << endl;
  58. }
  59. return 0;
  60. }
本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号