简体   繁体   English

使用快速查找算法(Java)查找定向图中所有弱连通分量的优化

[英]Optimization for Find All Weakly Connected Components in Directed Graph Using Quick-Find Algorithm (Java)

I'm seeking to improve my solution to find all weakly connected components in a directed graph using Quick-Find algorithm. 我正在寻求改进我的解决方案,使用Quick-Find算法在有向图中找到所有弱连接的组件。

Problem Statement 问题陈述

Given a list of DirectedGraphNode , find all islands (ie weakly connected components). 给定DirectedGraphNode列表,找到所有岛(即弱连接组件)。

public class DirectedGraphNode {
    String val;
    List<DirectedGraphNode> neighbors;
}

Thus, given following directed graph: 因此,给出以下有向图:

A —> B —> <— C 
     ^
     |
     E <— F —> D —> G

X -> <- Y

node : neighbors
  A  :  [B]
  B  :  [C, E]
  C  :  [B]
  D  :  [G]
  E  :  []
  F  :  [E, D]
  G  :  []
  X  :  [Y]
  Y  :  [X]

The output should be as follows (order doesn't matter): 输出应如下(顺序无关紧要):

[
   [A, B, C, E, D, F, G],
   [X, Y]
]

I solved this using Quick-Find algorithm. 我使用Quick-Find算法解决了这个问题。 Code below: 代码如下:

public static List<List<Node>> connectedComponents(List<Node> nodes) {
    if (nodes == null || nodes.size() == 0) {
        throw new IllegalArgumentException("List node is empty");
    }

    // Maintain array with name for each element
    String[] labels = new String[nodes.size()];
    // Initially, set the labels of each element to itself
    // Use HashMap to memorize the index
    Map<String, Integer> map = new HashMap<>();
    for (int i = 0; i < labels.length; i++) {
        labels[i] = nodes.get(i).val;
        map.put(nodes.get(i).val, i);
    }

    for (Node node : nodes) {
        if (node.neighbors == null || node.neighbors.isEmpty()) {
            continue;
        }

        int changerIdx = map.get(node.val);
        for (Node nbr : node.neighbors) {
            int changeeIdx = map.get(nbr.val);
            String symbol = labels[changeeIdx];
            for (int i = 0; i < labels.length; i++) {
                if (labels[i] == symbol) {
                    labels[i] = labels[changerIdx];
                }
            }
        }
    }
    return createIslandList(labels, nodes);
}

private static List<List<Node>> createIslandList(String[] labels, List<Node> nodes) {
    List<List<Node>> res = new ArrayList<List<Node>>();
    if (labels == null || labels.length == 0) {
        return res;
    }

    Map<String, List<Node>> map = new HashMap<String, List<Node>>();
    for (int i = 0; i < labels.length; i++) {
        if (!map.containsKey(labels[i])) {
            List<Node> island = new ArrayList<>();
            island.add(nodes.get(i));
            map.put(labels[i], island);
        } else {
            map.get(labels[i]).add(nodes.get(i));
        }
    }

    for (String key : map.keySet()) {
        res.add(map.get(key));
    }

    return res;
}

However, this algorithm in the worst case runs in O(N^3) since each time it needs to do linear search for union. 然而,在最坏的情况下,该算法在O(N ^ 3)中运行,因为每次它需要对并集进行线性搜索。 I'm very curious if there is any way to improve this. 如果有任何方法可以改善这一点,我很好奇。

Thank you for your suggestion! 谢谢你的建议!

This is an edited answer. 这是一个经过编辑的答案。 Sorry that I was confused between weakly connected components and strongly connected components. 对不起,我对弱连接组件和强连接组件感到困惑。

It's actually very straightforward to determine weakly connected components. 实际上,确定弱连接组件非常简单。 Just convert all edges to be undirected and perform BFS or DFS. 只需将所有边转换为无向并执行BFS或DFS。

The run time will be O(|V| + |E|) where V is the set of vertices and E is the set of edges. 运行时间为O(|V| + |E|) ,其中V是顶点集, E是边集。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM