Skip to content
This repository was archived by the owner on Jun 18, 2026. It is now read-only.

Commit 10eebd4

Browse files
refactor: deduplicate countComponents and bfsDistances into GraphUtils
Added GraphUtils.countComponents(Graph) — counts connected components without allocating per-component Sets or sorting (just a visited set + BFS counter). 4 callers were using findComponents(g).size() which built the full component list, sorted it, then discarded everything except the count. Also replaced GraphPowerCalculator's private bfsDistances() with a one-line delegate to GraphUtils.bfsDistances() — same BFS logic was duplicated verbatim (~15 lines). Files changed: - GraphUtils.java: +countComponents() - GraphPowerCalculator.java: -15 lines (delegate to GraphUtils) - GraphResilienceAnalyzer.java: delegate to GraphUtils.countComponents - GraphSparsificationAnalyzer.java: delegate to GraphUtils.countComponents - FeedbackVertexSetAnalyzer.java: delegate to GraphUtils.countComponents - TreeAnalyzer.java: delegate to GraphUtils.countComponents
1 parent e1b857e commit 10eebd4

6 files changed

Lines changed: 40 additions & 20 deletions

File tree

Gvisual/src/gvisual/FeedbackVertexSetAnalyzer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ public int cycleRank() {
213213
}
214214

215215
private int countComponents() {
216-
return GraphUtils.findComponents(graph).size();
216+
return GraphUtils.countComponents(graph);
217217
}
218218

219219
// ── Bounds ────────────────────────────────────────────────────

Gvisual/src/gvisual/GraphPowerCalculator.java

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -69,21 +69,7 @@ public Map<String, Map<String, Integer>> allPairsDistances() {
6969
}
7070

7171
private Map<String, Integer> bfsDistances(String source) {
72-
Map<String, Integer> dist = new LinkedHashMap<>();
73-
Queue<String> queue = new ArrayDeque<>();
74-
dist.put(source, 0);
75-
queue.add(source);
76-
while (!queue.isEmpty()) {
77-
String current = queue.poll();
78-
int d = dist.get(current);
79-
for (String neighbor : graph.getNeighbors(current)) {
80-
if (!dist.containsKey(neighbor)) {
81-
dist.put(neighbor, d + 1);
82-
queue.add(neighbor);
83-
}
84-
}
85-
}
86-
return dist;
72+
return GraphUtils.bfsDistances(graph, source);
8773
}
8874

8975
/**

Gvisual/src/gvisual/GraphResilienceAnalyzer.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -324,8 +324,7 @@ private int largestComponentSize(Graph<String, Edge> g) {
324324
}
325325

326326
private int countComponents(Graph<String, Edge> g) {
327-
if (g.getVertexCount() == 0) return 0;
328-
return GraphUtils.findComponents(g).size();
327+
return GraphUtils.countComponents(g);
329328
}
330329

331330
private double globalEfficiency(Graph<String, Edge> g) {

Gvisual/src/gvisual/GraphSparsificationAnalyzer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ public SparsificationQuality evaluateQuality(Graph<String, Edge> sparse) {
271271
}
272272

273273
private int countComponents(Graph<String, Edge> g) {
274-
return GraphUtils.findComponents(g).size();
274+
return GraphUtils.countComponents(g);
275275
}
276276

277277
private double degreeCorr(Graph<String, Edge> g1, Graph<String, Edge> g2) {

Gvisual/src/gvisual/GraphUtils.java

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,41 @@ public static List<Set<String>> findComponents(
171171
return components;
172172
}
173173

174+
/**
175+
* Counts the number of connected components without building or sorting
176+
* the full component list. Use this instead of
177+
* {@code findComponents(graph).size()} when only the count is needed.
178+
*
179+
* @param graph the JUNG graph
180+
* @return number of connected components
181+
*/
182+
public static int countComponents(Graph<String, Edge> graph) {
183+
Set<String> visited = new HashSet<String>();
184+
int count = 0;
185+
for (String vertex : graph.getVertices()) {
186+
if (!visited.contains(vertex)) {
187+
count++;
188+
// Inline BFS to mark visited without building a component set
189+
ArrayDeque<String> queue = new ArrayDeque<String>();
190+
visited.add(vertex);
191+
queue.add(vertex);
192+
while (!queue.isEmpty()) {
193+
String current = queue.poll();
194+
Collection<Edge> incident = graph.getIncidentEdges(current);
195+
if (incident == null) continue;
196+
for (Edge e : incident) {
197+
String neighbor = getOtherEnd(e, current);
198+
if (neighbor != null && !visited.contains(neighbor)) {
199+
visited.add(neighbor);
200+
queue.add(neighbor);
201+
}
202+
}
203+
}
204+
}
205+
}
206+
return count;
207+
}
208+
174209
/**
175210
* Finds the largest connected component.
176211
*

Gvisual/src/gvisual/TreeAnalyzer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -776,7 +776,7 @@ private void requireTree() {
776776
}
777777

778778
private int countComponents() {
779-
return GraphUtils.findComponents(graph).size();
779+
return GraphUtils.countComponents(graph);
780780
}
781781

782782
private void computeSubtreeSizes(String root, Map<String, Integer> subtreeSize,

0 commit comments

Comments
 (0)