深度优先搜索实现无向图环的检测(java实现)
一、问题描述
如何检测无向图中的环?注意:本题中不考虑自环和平行环
二、解决思路
由于深度优先搜索性质,我们可以用它来检测环。假设当前访问顶点为v,访问v之前访问的顶点为prev,则prev为v的前驱节点。设w为v的后继节点,且w != prev并且w已被访问了,则可以判断图中存在环;假设第一个访问的顶点的前驱节点为其本身,我们以图1 为例进行讲解:
第一步:我们先访问0号顶点,此时v = 0 , prev = 0,w = 1。满足w != prev,但不满足w以访问,继续执行下一步;如下图:
第二步:我们访问1号顶点,此时v = 1,prev = 0,w = 2或3;不满足条件继续执行如下图所示:
第三步:我们访问2号顶点,此时v = 2,prev = 1,w = 1或3;不满足条件继续执行,如下图所示:
第四步:我们访问3号顶点,此时v = 3,prev = 2;两种情况,第一种情况:w = 2,v = 3,prev = 2不满足w != prev;第二种情况:w = 1,v = 3,prev = 2满足w != prev并且满足w已经访问,所以该图是一个有环图。
三、算法实现
package graph; import java.util.Arrays; /** * 通过深度优先搜索检测图中是否存在环 * * @date 2021-01-22 15:18 * @author hh */ public class CycleTest { /** * 图对象 */ private Graph graph; /** * 标记哪些顶点被访问 */ private boolean[] marked; /** * 是否存在环 */ private boolean isHasCycle; private CycleTest() { } public boolean hasCycle(){ return isHasCycle; } public CycleTest(Graph graph) { this.graph = graph; //默认不存在环 this.isHasCycle = false; marked = new boolean[graph.getVertices()]; Arrays.fill(marked,Boolean.FALSE); this.dfs(); } /** * 深度优先搜索 */ public void dfs(){ for(int v = 0; v < graph.getVertices(); v++ ){ if(!isMarked(v)){ this.search(v,v); } } } private void search(int v,int prev){ System.out.print(v +" "); marked[v] = true; for(Integer w : graph.adj(v)){ if(!isMarked(w)){ search(w,v); }else if (w != prev){ isHasCycle = true; } } } /** * 顶点w是否被访问过 * @param w :顶点编号 * @return ;是否被访问 */ private boolean isMarked(int w){ return this.marked[w]; } }
测试代码如下所示:
public static void main(String[] args) throws Exception { String filename = "D:\Desktop\graph5.txt"; Graph graph = new Graph(); graph.createGraphByFile(filename); CycleTest cycleTest = new CycleTest(graph); boolean hasCycle = cycleTest.hasCycle(); System.out.print(" 是否存在环:" + hasCycle); }
下一篇:
864. 获取所有钥匙的最短路径