99import java .util .Set ;
1010import java .util .Stack ;
1111
12- public class HierholzerAlgorithm {
12+ /**
13+ * Implementation of Hierholzer's algorithm to find an Eulerian Circuit in an undirected graph.
14+ * <p>
15+ * An Eulerian circuit is a trail in a graph that visits every edge exactly once,
16+ * starting and ending at the same vertex. This algorithm finds such a circuit if one exists.
17+ * </p>
18+ * <p>
19+ * This implementation is designed for an <strong>undirected graph</strong>. For a valid Eulerian
20+ * circuit to exist, the graph must satisfy two conditions:
21+ * <ol>
22+ * <li>All vertices with a non-zero degree must be part of a single connected component.</li>
23+ * <li>Every vertex must have an even degree (an even number of edges connected to it).</li>
24+ * </ol>
25+ * </p>
26+ * <p>
27+ * The algorithm runs in O(E + V) time, where E is the number of edges and V is the number of vertices.
28+ * The graph is represented by a Map where keys are vertices and values are a LinkedList of adjacent vertices.
29+ * </p>
30+ *
31+ * @see <a href="https://en.wikipedia.org/wiki/Eulerian_path#Hierholzer's_algorithm">Wikipedia: Hierholzer's algorithm</a>
32+ */
33+ public final class HierholzerAlgorithm {
1334
1435 private final Map <Integer , LinkedList <Integer >> graph ;
1536
@@ -22,18 +43,13 @@ public boolean hasEulerianCircuit() {
2243 return true ;
2344 }
2445
25- // FINAL FIX: Loop over values directly for efficiency.
2646 for (List <Integer > neighbors : graph .values ()) {
2747 if (neighbors .size () % 2 != 0 ) {
2848 return false ;
2949 }
3050 }
3151
32- if (!isCoherentlyConnected ()) {
33- return false ;
34- }
35-
36- return true ;
52+ return isCoherentlyConnected ();
3753 }
3854
3955 public List <Integer > findEulerianCircuit () {
@@ -47,10 +63,9 @@ public List<Integer> findEulerianCircuit() {
4763 }
4864
4965 Stack <Integer > currentPath = new Stack <>();
50- List <Integer > circuit = new LinkedList <>();
66+ LinkedList <Integer > circuit = new LinkedList <>();
5167
5268 int startVertex = -1 ;
53- // FINAL FIX: Use entrySet for efficiency.
5469 for (Map .Entry <Integer , LinkedList <Integer >> entry : tempGraph .entrySet ()) {
5570 if (!entry .getValue ().isEmpty ()) {
5671 startVertex = entry .getKey ();
@@ -75,7 +90,8 @@ public List<Integer> findEulerianCircuit() {
7590 tempGraph .get (nextVertex ).remove (Integer .valueOf (currentVertex ));
7691 currentPath .push (nextVertex );
7792 } else {
78- circuit .add (0 , currentPath .pop ());
93+ circuit .addFirst (currentVertex );
94+ currentPath .pop ();
7995 }
8096 }
8197
@@ -90,7 +106,6 @@ private boolean isCoherentlyConnected() {
90106 Set <Integer > visited = new HashSet <>();
91107 int startNode = -1 ;
92108
93- // FINAL FIX: Use entrySet for efficiency.
94109 for (Map .Entry <Integer , LinkedList <Integer >> entry : graph .entrySet ()) {
95110 if (!entry .getValue ().isEmpty ()) {
96111 startNode = entry .getKey ();
@@ -104,7 +119,6 @@ private boolean isCoherentlyConnected() {
104119
105120 dfs (startNode , visited );
106121
107- // FINAL FIX: Use entrySet for efficiency.
108122 for (Map .Entry <Integer , LinkedList <Integer >> entry : graph .entrySet ()) {
109123 if (!entry .getValue ().isEmpty () && !visited .contains (entry .getKey ())) {
110124 return false ;
0 commit comments