🏳️🌈三、以下是使用递归方式遍历无向图的 C++ 代码示例:
classundigraph{public:voidDFS(intv){cout <<"顶点"<<v <<"被访问!"<<endl;visited[v]=true;for(intprev =smallestadjvertex(v);prev >=0;prev =nextadjvertex(v,prev)){if(visited[prev]==false){DFS(prev);}}}intsmallestadjvertex(intv){for(inti =0;i <vertexnum;i++){if(adjmatrix[v][i]==1){returni;}return-1;}}intnextadjvertex(intv,intprev){for(inti =prev +1;i <vertexnum;i++){if(adjmatrix[v][i]==1){returni;}return-1;}}voidDFStraverse(){for(inti =0;i <vertexnum;i++){visited[i]=false;}for(inti =0;i <vertexnum;i++){if(visited[i]==false){DFS(i);}}}private:boolvisited[maxsize];intadjmatrix[maxsize][maxsize];intvertexnum;};
在这段代码中,undigraph类表示无向图,其中DFS函数使用递归的方式遍历无向图中的节点,smallestadjvertex函数和nextadjvertex函数分别用于寻找当前节点的最小序号邻接顶点和下一个邻接顶点,DFStraverse函数用于遍历整个无向图。
💙(五)生成迷宫
DFS 可以用于生成随机迷宫。
💙(五)图的遍历
以无向图和二叉树的遍历为例,展示 DFS 在不同数据结构中的具体实现。
💚(四)大洋流水问题
在大洋流水问题中,我们可以从大洋开始向上流,利用 DFS 确定能流到太平洋和大西洋的位置。据统计,通过 DFS 可以在合理的时间内找到八皇后问题的所有 92 组解。
DFS 的工作方式类似于在迷宫中探索,一旦进入一个通道,就尽可能地沿着这个通道走到底,直到遇到死胡同或者已经没有未访问的分支,然后再回溯到上一个岔路口,尝试其他路径。这种方式不依赖于函数调用栈,因此可以处理深度较大的图而不会出现栈溢出问题。
与递归实现相比,迭代实现的代码较为冗长,但更加健壮。形象地说,DFS 就像是一个勇敢的探险家,不断深入未知领域,只有在走投无路时才会回头寻找其他可能性。例如,使用 DFS 生成一个 10x10 的迷宫,通常可以在几毫秒内完成。具体来说,我们从一个陆地格子开始,使用 DFS 遍历与其相邻的陆地格子,并记录遍历过的格子数量,即为该岛屿的面积。例如,在解决迷宫问题时,我们可以用一个二维数组模拟平面,用一个数组记录坐标是否被访问过,然后从起点开始,使用 DFS 算法不断尝试向四个方向移动,直到找到终点或者遍历完所有可能的路径。
例如,以下是使用递归方式解决迷宫问题的 C++ 代码示例:
#include<iostream>#include<vector>constintN =10;intmaze[N][N]={{1,1,1,1,1,1,1,1,1,1},{1,0,0,0,1,0,0,0,0,1},{1,0,1,0,1,0,1,1,0,1},{1,0,0,1,0,0,0,0,0,1},{1,0,1,0,0,1,0,1,0,1},{1,0,0,0,1,0,0,0,0,1},{1,0,1,0,1,0,1,0,1,1},{1,0,0,0,0,0,0,0,0,1},{1,0,1,0,1,0,1,1,0,1},{1,1,1,1,1,1,1,1,1,1}};std::vector<std::pair<int,int>>path;booldfs(intx,inty){if(x <0||x >=N ||y <0||y >=N)returnfalse;if(maze[x][y]==1)returnfalse;if(x ==N -1&&y ==N -1){path.emplace_back(x,y);returntrue;}maze[x][y]=1;path.emplace_back(x,y);if(dfs(x+1,y)||dfs(x-1,y)||dfs(x,y+1)||dfs(x,y-1)){returntrue;}path.pop_back();returnfalse;}intmain(){dfs(1,1);if(path.empty()){std::cout <<"No path found."<<std::endl;}else{std::cout <<"Path:"<<std::endl;for(constauto&p :path){std::cout <<"(" <<p.first <<"," <<p.second <<")" <<std::endl;}}return0;}
这段代码中,dfs函数使用递归的方式在迷宫中进行深度优先搜索,找到从起点到终点的路径。
在 C++ 中,DFS 可以通过递归或者显式栈来实现。据实际测试,对于一个中等规模的迷宫(如 10x10 的迷宫),DFS 可以在较短的时间内找到路径。中序和后序遍历的 C++ 代码示例:
structTreeNode{intval;TreeNode *left;TreeNode *right;TreeNode(intx):val(x),left(NULL),right(NULL){}};voidpreOrderRecur(TreeNode *root){if(!root)return;cout <<root->val <<" ";preOrderRecur(root->left);preOrderRecur(root->right);}voidinOrderRecur(TreeNode *root){if(!root)return;inOrderRecur(root->left);cout <<root->val <<" ";inOrderRecur(root->right);}voidpostOrderRecur(TreeNode *root){if(!root)return;postOrderRecur(root->left);postOrderRecur(root->right);cout <<root->val <<" ";}
在这段代码中,TreeNode结构体表示二叉树的节点,preOrderRecur函数、从图中的任意一个节点开始进行 DFS,如果能够访问到图中的所有节点,则说明该图是连通的;否则,图是不连通的。将起始节点压入栈中,并标记为已访问。寻找路径等问题。同时,我们可以使用一个栈或者向量来保存探索过程中的坐标,以便在找到终点后回溯得到完整的路径。以递归方式为例,我们从一个起始节点开始,标记该节点为已访问,然后遍历该节点的所有邻居节点。以递归方式为例,我们从起点开始,检查当前位置的四个方向(上、中序和后序遍历。其核心原理是从起始顶点开始,沿着路径尽可能深地探索,直到无法继续前进时才回溯。如果没有找到路径,则输出 “No path found.”。
🧡(二)岛屿问题
以最大岛屿面积问题为例,我们可以使用 DFS 在二维矩阵中解决这个问题。一种常见的方法是从一个随机的起点开始,不断地随机选择一个未访问的相邻节点进行扩展,直到无法继续扩展为止。在搜索过程中,我们可以使用一个二维数组来记录已经访问过的位置,以避免重复访问。
以下是使用 DFS 解决大洋流水问题的 C++ 代码示例:
classSolution{public:List<List<Integer>>pacificAtlantic(int[][]matrix){List<List<Integer>>res =newArrayList<>();if(matrix.length ==0||matrix[0].length ==0){returnres;}intr =matrix.length;intc =matrix[0].length;boolean[][]toPa =newboolean[r][c];boolean[][]toAt =newboolean[r][c];for(inti =0;i <r;i++){DFS(i,0,matrix,toPa,Integer.MIN_VALUE);