这里有一个无向图的深度遍历算法,无向图 深度优先遍历 c语言实现, 有向图的DFS遍历跟这个算法一样。
利用DFS判断一个有向图是否有环的思路是:对一个节点v进行深度遍历,判断是否能从v到达自己这个节点,即是否存在从v到v的环路。
在图的深度遍历中,我们将图中每个节点设置为三个状态:-1,0,1,分别表示还没发现的节点;已经发现但是还没处理完的节点;已经处理完的节点。对应上述思路,假设我们正在处理v,那么v的状态为0,其余正在处理节点的状态也为0,如果从状态为0的节点遍历到状态为0的节点就存在环。
下面是leetcode中的一个题:Course Schedule,可以用dfs来解决,代码如下(下面代码效率很低,仅用来说明用dfs发现环的思路),
import java.util.ArrayList;
import java.util.List;
public class Solution {
boolean flag = true;
public void dfs(List<List<Integer>> adjList,int v,int[] color){
color[v] = 0; //表示正在处理v节点
List<Integer> adjs = adjList.get(v);
for(int i=0;i<adjs.size();i++){
if(color[adjs.get(i)]==-1){
dfs(adjList,adjs.get(i),color);
}else if(color[adjs.get(i)]==0){//回到了状态为0的节点,有环
flag = false;
}
}
color[v] = 1;
}
public boolean canFinish(int numCourses, int[][] prerequisites) {
List<List<Integer>> adjList = new ArrayList<List<Integer>>();
//根据course个数初始化一个空的邻接表
for(int i=0;i<numCourses;i++){
adjList.add(new ArrayList<Integer>());
}
//初始化color数组
int[] color = new int[numCourses];
for(int i=0;i<numCourses;i++){
color[i] = -1;
}
//adjList表示邻接表,头结点是后面的课程,后面的list表示先修课
//由先修课指向 后修课
for(int i=0;i<prerequisites.length;i++){
int[] cp = prerequisites[i];
adjList.get(cp[1]).add(cp[0]);
}
//下面对邻接表进行深度遍历,看看是否有环,从每一个节点都遍历一次
for(int i=0;i<numCourses;i++){
dfs(adjList, i, color);
if(!flag){
return false;
}
for(int j=0;j<numCourses;j++){
color[j] = -1;
}
}
return flag;
}
public static void main(String[] args) {
Solution s = new Solution();
//4, [[0,1],[3,1],[1,3],[3,2]]
int[][] nums = {{0,1},{0,2},{1,2}};
System.out.println(s.canFinish(3, nums));
}
}