首先,这里的图不是指的我们一般所说的图结构,而是大小为M*N的矩形区域(也可以看成是一个矩阵)。而关于矩形区域的遍历问题经常出现,如“寻找矩阵中的路径”、“找到矩形区域的某个特殊点”等等之类的题目,在笔试的编程题中经常会出现。下面就这种类型的问题给出一个较为通用的模板:
利用深度优先搜索(DFS)
#include<iostream> #include<unordered_map> #include<queue> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> #include<sstream> #include<set> #include<map> using namespace std; #define M 100 #define N 100 //定义矩形区域的大小 bool visited[M][N];//设置访问标记数组;这里建成一维和二维消耗的空间是一样的,而且二维的更直观 int _map[M][N];//矩形区域的范围,往往由题目给出 /* Check函数: (1)两个最基本的条件:该区域未被访问过和未超出矩形区域的范围。 (2)根据题目要求,还可能有其他的限制条件和其他形参 */ bool Check(int c_row,int c_col,int rows,int cols,...)//用以检验当前位置是否合法 { if(!visited[c_row][c_col] && c_row >=0 && c_row < rows && c_col >= 0 && c_col < cols && ...) return true; else return false; } /* DFSTraverse函数: (1)函数的返回值类型根据具体题目可调整,有时也为int、bool型等 (2)函数的形参根据题目要求可能还有其他参数 (3)遍历的起始点根据题目调整 */ void DFSTraverse(int rows,int cols,..) { if(rows < 0 || cols < 0 || ...) return;//非法输入的处理 memset(visited,0,sizeof(visited));//初始化访问标记数组 DFS(0,0,rows,cols,...)//此处是以(0,0)开始遍历;根据题目可调整,也可以为所有的点 /* 或者 for(int i = 0; i < rows; i++) for(int j = 0; j < cols; j++) DFS(i,j,rows,cols,....) */ } /* DFS函数: (1)函数的形参根据题目要求可能还有其他参数 (2)函数的返回值不一定是void */ void DFS(int c_row,int c_col,int rows,int cols,...) { if(Check(c_row,c_col,rows,cols,...))//按照规则遍历相关节点 { DFS(c_row,c_col + 1,row,cols,...)... DFS(c_row + 1,c_col,row,cols,...)... //...表示相应的操作,如“+”、“||” DFS(c_row,c_col - 1,row,cols,...)... DFS(c_row - 1,c_col,row,cols,...)... ....//其他操作 } ....//其他操作 } int main() { DFSTraverse(M,N,....); }
整个DFS的过程和一般图的过程(见:https://www.cnblogs.com/wangkundentisy/p/9284886.html)类似,主要区别在于:
(1)矩形区域的限制条件更多,而一般图结构的限制条件就是顶点没被访问过。
(2)按规则遍历相关节点相当于一般图中的寻找邻接点的过程。
(3)矩形区域的DFS更灵活;这里可以结合《剑指offer(第二版)》面试题12和13来更好的理解。
(4)一般常见的DFS应用就是:树的遍历、图的遍历和矩形区域的遍历;要看题目属于哪一种类型。