用于查找双连通分量的非递归算法

时间:2017-01-10 11:32:50

标签: algorithm graph

有没有办法使用非递归DFS在无向图中找到双连通组件,以便它可以用于大型图形?

1 个答案:

答案 0 :(得分:0)

据我所知,它比一般的dfs复杂一点。 一般的尾递归打开循环相当不错。如果您有多个调用,但不使用子例程结果,那么它的解包也足够好。但是如果你使用结果,那么goto / break或代码重复会有点难看。

我必须像这样做一些丑陋的修改。说实话,我没有机会调试它,把它作为一般想法来制作你自己的代码。

import java.util.Stack;

private void dfs2(Graph G, int u, int v) {
    Stack<MyStackFrame> stack = new Stack<>();

    int children;
    int wi = -1;
    int w;

    do {
        if (wi < 0) { //start dfs
            children = 0;
            pre[v] = cnt++;
            low[v] = pre[v];
            for (wi = 0; wi < G.adj(v).length; wi++) {
                w = G.adj(v)[wi];
                if (pre[w] == -1) {
                    children++;
                    stack.push(new MyStackFrame(children, wi, u, v));
                    //dfs(G, v, w);
                    wi = -1;
                    u = v;
                    v = w;
                    break;
                }
                // update low number - ignore reverse of edge leading to v
                else if (w != u)
                    low[v] = Math.min(low[v], pre[w]);
            }
            if (wi < 0)
                break;
            // root of DFS is an articulation point if it has more than 1 child
            if (u == v && children > 1)
                articulation[v] = true;
        }
        else { // continue dfs
            MyStackFrame stackFrame = stack.pop();
            u = stackFrame.u;
            v = stackFrame.v;
            children = stackFrame.children;
            wi = stackFrame.wi;
            w = G.adj(v)[wi];

            // update low number
            low[v] = Math.min(low[v], low[w]);

            // non-root of DFS is an articulation point if low[w] >= pre[v]
            if (low[w] >= pre[v] && u != v) 
                articulation[v] = true;
            wi++;

            for (; wi < G.adj(v).length; wi++) {
                w = G.adj(v)[wi];
                if (pre[w] == -1) {
                    children++;
                    stack.push(new MyStackFrame(children, wi, u, v));
                    //dfs(G, v, w);
                    wi = -1;
                    u = v;
                    v = w;
                    break;
                }
                // update low number - ignore reverse of edge leading to v
                else if (w != u)
                    low[v] = Math.min(low[v], pre[w]);
            }
            if (wi < 0)
                break;

            // root of DFS is an articulation point if it has more than 1 child
            if (u == v && children > 1)
                articulation[v] = true;
        }
    } while (!stack.empty());       
}