判断有向图是否有环

要想对一副有向图进行拓扑排序,必须要保证有向图是无环的,那么我们如何判断图是否含有环呢?我们可以使用深度优先搜索来遍历图,并创建一个数组来标记顶点是否已经在递归栈中,这样,当一个顶点指向的顶点已经在递归栈中,说明存在一个环,使用一个数组来记录当前遍历节点的上一个节点,这样就能得到这个环中的所有节点了。
有向环的API
public calss DirectedCycle
DirectedCycle(Digraph G) 寻找有向环的构造函数
boolean hasCycle() 是否存在环
Iterable cycle() 有向环中的所有节点(如果存在)
具体代码实现:

public class DirectedCycle{
    private boolean[] marked;                                     //是否已经遍历过
    private boolean[] onStack;                                    //是否在递归栈中
    private int[]     edgeTo;                                     //记录当前节点的前一个节点
    private Stack<Integer> cycle;                                 //环中的所有节点
    //Digraph类请看前面的一篇有向图的邻接表实现
    public DirectedCycle(Digraph G){
        marked = new boolean[G.V()];
        onStack = new boolean[G.V()];
        edgeTo = new int[G.V()];
        for(int i=0;i<G.V();i++){
            dfs(G,i);
        }
    }
    //深度优先搜索
    private void dfs(Digraph G, int v){
        onStack[v] = true;                       //把当前节点加入递归栈
        marked[v] = true;                         //标记当前节点已访问过
        for(int w:G.adj(v)){
            if(this.hasCycle()) return;
            else if(!marked[w]){
                edgeTo[w] = v;
                dfs(G,w);
            }
            //如果w已在栈中,说明存在栈
            else if(onStack[w]){
                cycle = new Stack<Integer>();
                for(int i=v;i!=w;i = edgeTo[i]){
                    cycle.push(i);
                }
                cycle.push(w);
                cycle.push(v);
            }

        }
        onStack[v] = false;
    }

    //判断是否有环
    public boolean hasCycle(){
        return cycle!=null;
    }

    //返回环中的所有节点
    public Iterable<Integer> cycle(){
        return cycle;
    }
}

猜你喜欢

转载自blog.csdn.net/qq_37520037/article/details/82121239