用快速查找算法(Java)优化查找有向图中所有弱连通分量
我正在寻求改进我的解决方案,使用快速查找算法查找有向图中的所有弱连通分量 问题陈述 给定用快速查找算法(Java)优化查找有向图中所有弱连通分量,java,algorithm,graph,connected-components,union-find,Java,Algorithm,Graph,Connected Components,Union Find,我正在寻求改进我的解决方案,使用快速查找算法查找有向图中的所有弱连通分量 问题陈述 给定DirectedGraphNode列表,查找所有孤岛(即弱连接组件) 我使用快速查找算法解决了这个问题。代码如下: public static List<List<Node>> connectedComponents(List<Node> nodes) { if (nodes == null || nodes.size() == 0) { throw
DirectedGraphNode
列表,查找所有孤岛(即弱连接组件)
我使用快速查找算法解决了这个问题。代码如下:
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;
}
公共静态列表已连接组件(列表节点){
if(nodes==null | | nodes.size()==0){
抛出新的IllegalArgumentException(“列表节点为空”);
}
//使用每个元素的名称维护数组
String[]labels=新字符串[nodes.size()];
//最初,将每个元素的标签设置为自身
//使用HashMap来记忆索引
Map Map=newhashmap();
对于(int i=0;i
然而,在最坏的情况下,该算法在O(N^3)中运行,因为每次它都需要对并集进行线性搜索。我很好奇是否有任何方法可以改进这一点
谢谢你的建议 这是一个经过编辑的答案。很抱歉,我混淆了弱连接组件和强连接组件 确定弱连接组件实际上非常简单。只需将所有边转换为无向,并执行BFS或DFS
运行时间将是
O(|V |+| E |)
其中V
是顶点集,E
是边集。我不确定JGraphT的性能,所以只需提示一下:“目前,inspector支持无向图的连接组件和有向图的弱连接组件”Java实现:@wooke919我只是想知道将所有边转换为无向的运行时复杂性。进行此转换的好方法是什么?@gyoho如果B
是a
的邻居,则添加a
作为B
的邻居。这将花费O(| E |)
时间。@Wooke919为了进一步优化,我将邻居的数据结构从List
更改为Set
,以实现O(1)
查找以搜索邻居,以避免添加重复项。
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]
[
[A, B, C, E, D, F, G],
[X, Y]
]
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;
}