Skip to content

Commit 0fac806

Browse files
committed
fix: Apply all formatting, style, and efficiency fixes
1 parent 96bd4fc commit 0fac806

File tree

2 files changed

+20
-82
lines changed

2 files changed

+20
-82
lines changed

src/main/java/com/thealgorithms/graph/HierholzerAlgorithm.java

Lines changed: 20 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -9,83 +9,51 @@
99
import java.util.Set;
1010
import java.util.Stack;
1111

12-
/**
13-
* An implementation of Hierholzer's Algorithm to find an Eulerian Path or Circuit in an undirected graph.
14-
* An Eulerian path is a trail in a graph that visits every edge exactly once.
15-
* An Eulerian circuit is an Eulerian path that starts and ends at the same vertex.
16-
*
17-
* Wikipedia: https://en.wikipedia.org/wiki/Eulerian_path#Hierholzer's_algorithm
18-
*/
1912
public class HierholzerAlgorithm {
2013

21-
private final int numVertices;
2214
private final Map<Integer, LinkedList<Integer>> graph;
2315

24-
/**
25-
* Constructor for the algorithm.
26-
* @param graph The graph represented as an adjacency list.
27-
* Using a LinkedList for neighbors is efficient for edge removal.
28-
*/
2916
public HierholzerAlgorithm(Map<Integer, LinkedList<Integer>> graph) {
30-
if (graph == null) {
31-
this.graph = new HashMap<>();
32-
this.numVertices = 0;
33-
return;
34-
}
35-
this.graph = graph;
36-
this.numVertices = graph.size();
17+
this.graph = (graph == null) ? new HashMap<>() : graph;
3718
}
3819

39-
/**
40-
* Checks if an Eulerian circuit exists in the undirected graph.
41-
* Condition: All vertices with a non-zero degree must be in a single connected component,
42-
* and all vertices must have an even degree.
43-
* @return true if a circuit exists, false otherwise.
44-
*/
4520
public boolean hasEulerianCircuit() {
4621
if (graph.isEmpty()) {
47-
return true; // An empty graph has an empty circuit.
22+
return true;
4823
}
4924

50-
// Check 1: All vertices must have an even degree.
51-
for (int vertex : graph.keySet()) {
52-
if (graph.get(vertex).size() % 2 != 0) {
53-
return false; // Found a vertex with an odd degree.
25+
// FINAL FIX: Loop over values directly for efficiency.
26+
for (List<Integer> neighbors : graph.values()) {
27+
if (neighbors.size() % 2 != 0) {
28+
return false;
5429
}
5530
}
5631

57-
// Check 2: All vertices with edges must be connected.
5832
if (!isCoherentlyConnected()) {
5933
return false;
6034
}
6135

6236
return true;
6337
}
6438

65-
/**
66-
* Finds the Eulerian circuit.
67-
* @return A list of vertices representing the circuit, or an empty list if none exists.
68-
*/
6939
public List<Integer> findEulerianCircuit() {
7040
if (!hasEulerianCircuit()) {
7141
return Collections.emptyList();
7242
}
7343

74-
// Create a copy of the graph to avoid modifying the original during traversal.
7544
Map<Integer, LinkedList<Integer>> tempGraph = new HashMap<>();
7645
for (Map.Entry<Integer, LinkedList<Integer>> entry : graph.entrySet()) {
7746
tempGraph.put(entry.getKey(), new LinkedList<>(entry.getValue()));
7847
}
7948

80-
// Data structures for the algorithm.
8149
Stack<Integer> currentPath = new Stack<>();
8250
List<Integer> circuit = new LinkedList<>();
8351

84-
// Find a starting vertex (any vertex with edges).
8552
int startVertex = -1;
86-
for (int vertex : tempGraph.keySet()) {
87-
if (!tempGraph.get(vertex).isEmpty()) {
88-
startVertex = vertex;
53+
// FINAL FIX: Use entrySet for efficiency.
54+
for (Map.Entry<Integer, LinkedList<Integer>> entry : tempGraph.entrySet()) {
55+
if (!entry.getValue().isEmpty()) {
56+
startVertex = entry.getKey();
8957
break;
9058
}
9159
}
@@ -94,36 +62,26 @@ public List<Integer> findEulerianCircuit() {
9462
if (graph.isEmpty()) {
9563
return Collections.emptyList();
9664
}
97-
return Collections.singletonList(graph.keySet().iterator().next()); // Graph with one isolated vertex.
65+
return Collections.singletonList(graph.keySet().iterator().next());
9866
}
9967

10068
currentPath.push(startVertex);
10169

10270
while (!currentPath.isEmpty()) {
10371
int currentVertex = currentPath.peek();
10472

105-
// If the current vertex has unvisited edges
10673
if (tempGraph.containsKey(currentVertex) && !tempGraph.get(currentVertex).isEmpty()) {
107-
int nextVertex = tempGraph.get(currentVertex).pollFirst(); // Get a neighbor
108-
109-
// Remove the reverse edge as well (for undirected graph)
74+
int nextVertex = tempGraph.get(currentVertex).pollFirst();
11075
tempGraph.get(nextVertex).remove(Integer.valueOf(currentVertex));
111-
112-
// Push the neighbor to the stack to continue the tour
11376
currentPath.push(nextVertex);
11477
} else {
115-
// If "stuck" (no more edges), backtrack and add to the final circuit.
11678
circuit.add(0, currentPath.pop());
11779
}
11880
}
11981

12082
return circuit;
12183
}
12284

123-
/**
124-
* Helper method to check if all vertices with a non-zero degree are connected.
125-
* Uses a simple traversal (DFS).
126-
*/
12785
private boolean isCoherentlyConnected() {
12886
if (graph.isEmpty()) {
12987
return true;
@@ -132,26 +90,24 @@ private boolean isCoherentlyConnected() {
13290
Set<Integer> visited = new HashSet<>();
13391
int startNode = -1;
13492

135-
// Find the first vertex with a degree greater than 0
136-
for (int vertex : graph.keySet()) {
137-
if (!graph.get(vertex).isEmpty()) {
138-
startNode = vertex;
93+
// FINAL FIX: Use entrySet for efficiency.
94+
for (Map.Entry<Integer, LinkedList<Integer>> entry : graph.entrySet()) {
95+
if (!entry.getValue().isEmpty()) {
96+
startNode = entry.getKey();
13997
break;
14098
}
14199
}
142100

143-
// If no edges in the graph, it's connected.
144101
if (startNode == -1) {
145102
return true;
146103
}
147104

148-
// Perform DFS from the start node
149105
dfs(startNode, visited);
150106

151-
// Check if all vertices with edges were visited
152-
for (int vertex : graph.keySet()) {
153-
if (!graph.get(vertex).isEmpty() && !visited.contains(vertex)) {
154-
return false; // Found a vertex with edges that wasn't visited
107+
// FINAL FIX: Use entrySet for efficiency.
108+
for (Map.Entry<Integer, LinkedList<Integer>> entry : graph.entrySet()) {
109+
if (!entry.getValue().isEmpty() && !visited.contains(entry.getKey())) {
110+
return false;
155111
}
156112
}
157113
return true;

src/test/java/com/thealgorithms/graph/HierholzerAlgorithmTest.java

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -16,55 +16,37 @@ public class HierholzerAlgorithmTest {
1616

1717
@Test
1818
public void testFindsEulerianCircuitInSimpleTriangleGraph() {
19-
// Create a simple triangle graph where a circuit definitely exists: 0-1, 1-2, 2-0
2019
Map<Integer, LinkedList<Integer>> graph = new HashMap<>();
2120
graph.put(0, new LinkedList<>(Arrays.asList(1, 2)));
2221
graph.put(1, new LinkedList<>(Arrays.asList(0, 2)));
2322
graph.put(2, new LinkedList<>(Arrays.asList(0, 1)));
24-
2523
HierholzerAlgorithm algorithm = new HierholzerAlgorithm(graph);
26-
27-
// Verify that the algorithm agrees a circuit exists
2824
assertTrue(algorithm.hasEulerianCircuit());
29-
3025
List<Integer> circuit = algorithm.findEulerianCircuit();
31-
32-
// A valid circuit for a triangle has 3 edges, so the path will have 4 vertices (e.g., 0 -> 1 -> 2 -> 0)
3326
assertEquals(4, circuit.size());
34-
35-
// The path must start and end at the same vertex
3627
assertEquals(circuit.get(0), circuit.get(circuit.size() - 1));
3728
}
3829

3930
@Test
4031
public void testFailsForGraphWithOddDegreeVertices() {
41-
// Create a graph where vertices 0 and 1 have an odd degree (1)
4232
Map<Integer, LinkedList<Integer>> graph = new HashMap<>();
4333
graph.put(0, new LinkedList<>(Collections.singletonList(1)));
4434
graph.put(1, new LinkedList<>(Collections.singletonList(0)));
45-
4635
HierholzerAlgorithm algorithm = new HierholzerAlgorithm(graph);
47-
48-
// The algorithm should correctly identify that no circuit exists
4936
assertFalse(algorithm.hasEulerianCircuit());
50-
// The find method should return an empty list
5137
assertTrue(algorithm.findEulerianCircuit().isEmpty());
5238
}
5339

5440
@Test
5541
public void testFailsForDisconnectedGraph() {
56-
// Create a graph with two separate triangles (0-1-2 and 3-4-5)
5742
Map<Integer, LinkedList<Integer>> graph = new HashMap<>();
5843
graph.put(0, new LinkedList<>(Arrays.asList(1, 2)));
5944
graph.put(1, new LinkedList<>(Arrays.asList(0, 2)));
6045
graph.put(2, new LinkedList<>(Arrays.asList(0, 1)));
6146
graph.put(3, new LinkedList<>(Arrays.asList(4, 5)));
6247
graph.put(4, new LinkedList<>(Arrays.asList(3, 5)));
6348
graph.put(5, new LinkedList<>(Arrays.asList(3, 4)));
64-
6549
HierholzerAlgorithm algorithm = new HierholzerAlgorithm(graph);
66-
67-
// All degrees are even, but the graph is not connected, so no circuit exists
6850
assertFalse(algorithm.hasEulerianCircuit());
6951
}
7052

0 commit comments

Comments
 (0)