赞
踩
目录索引:畅游面试中算法题集锦
小规律:树边、前向边,都是往前指,即顺着bfs遍历的顺序;回边是往回指,即逆着bfs遍历的顺序;横跨边横着指,即边的两个端点没有祖先、后裔关系
深度优先遍历(DFS) 可用于检测图中的环。连通图的DFS生成树。只有当图中存在 回边(back edge) 时,图中才存在环。
回边(back edge) 是从一个节点到它自己(自循环)或DFS生成的树中它的一个祖先的边。
在下图中,有3条回边(back edge),用十字标记。我们可以观察到,这3条后边表示图中存在3个环。
对于非联通的图,获取DFS树作为输出。要检测有没有环,通过检查**回边(back edge)**来检查单个树的有没有环。
为了检测回边(back edge),跟踪函数递归堆栈中当前的顶点,用于DFS遍历。
如果到达的顶点已经在递归堆栈中,那么树中就存在一个环。
将当前顶点与递归堆栈中的顶点连接的边称为回边(back edge)。
用recStack[]
数组来记录递归堆栈中的顶点。
visited
和recursion
stack
。recursion
stack
中标记索引。recursion
stack
中标记,则返回true。static class Graph { public int V; //顶点的数量 public List<List<Integer>> adj; // 邻接表 public Graph(int V) { this.V = V; adj = new ArrayList<>(); for (int i = 0; i < V; i++) { adj.add(new ArrayList<>()); } } private void addEdge(int source, int dest) { adj.get(source).add(dest); } private boolean isCyclicUtil(int i, boolean[] visited, boolean[] recStack) { if (recStack[i]) return true; if (visited[i]) return false; visited[i] = true; recStack[i] = true; for (Integer next : adj.get(i)) { if (isCyclicUtil(next, visited, recStack)) return true; } recStack[i] = false; return false; } private boolean isCyclic() { boolean[] visited = new boolean[V]; boolean[] recStack = new boolean[V]; for (int i = 0; i < V; i++) { if(isCyclicUtil(i,visited,recStack)) return true; } return false; } public static void main(String[] args) { Graph graph = new Graph(4); graph.addEdge(0, 1); graph.addEdge(0, 2); graph.addEdge(1, 2); graph.addEdge(2, 0); graph.addEdge(2, 3); graph.addEdge(3, 3); if (graph.isCyclic()) System.out.println("Graph contains cycle"); else System.out.println("Graph doesn't contain cycle"); } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。