forked from TheAlgorithms/Java
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathHierholzerAlgorithm.java
More file actions
126 lines (102 loc) · 3.55 KB
/
HierholzerAlgorithm.java
File metadata and controls
126 lines (102 loc) · 3.55 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
package com.thealgorithms.graph;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Stack;
public class HierholzerAlgorithm {
private final Map<Integer, LinkedList<Integer>> graph;
public HierholzerAlgorithm(Map<Integer, LinkedList<Integer>> graph) {
this.graph = (graph == null) ? new HashMap<>() : graph;
}
public boolean hasEulerianCircuit() {
if (graph.isEmpty()) {
return true;
}
// FINAL FIX: Loop over values directly for efficiency.
for (List<Integer> neighbors : graph.values()) {
if (neighbors.size() % 2 != 0) {
return false;
}
}
if (!isCoherentlyConnected()) {
return false;
}
return true;
}
public List<Integer> findEulerianCircuit() {
if (!hasEulerianCircuit()) {
return Collections.emptyList();
}
Map<Integer, LinkedList<Integer>> tempGraph = new HashMap<>();
for (Map.Entry<Integer, LinkedList<Integer>> entry : graph.entrySet()) {
tempGraph.put(entry.getKey(), new LinkedList<>(entry.getValue()));
}
Stack<Integer> currentPath = new Stack<>();
List<Integer> circuit = new LinkedList<>();
int startVertex = -1;
// FINAL FIX: Use entrySet for efficiency.
for (Map.Entry<Integer, LinkedList<Integer>> entry : tempGraph.entrySet()) {
if (!entry.getValue().isEmpty()) {
startVertex = entry.getKey();
break;
}
}
if (startVertex == -1) {
if (graph.isEmpty()) {
return Collections.emptyList();
}
return Collections.singletonList(graph.keySet().iterator().next());
}
currentPath.push(startVertex);
while (!currentPath.isEmpty()) {
int currentVertex = currentPath.peek();
if (tempGraph.containsKey(currentVertex) && !tempGraph.get(currentVertex).isEmpty()) {
int nextVertex = tempGraph.get(currentVertex).pollFirst();
tempGraph.get(nextVertex).remove(Integer.valueOf(currentVertex));
currentPath.push(nextVertex);
} else {
circuit.add(0, currentPath.pop());
}
}
return circuit;
}
private boolean isCoherentlyConnected() {
if (graph.isEmpty()) {
return true;
}
Set<Integer> visited = new HashSet<>();
int startNode = -1;
// FINAL FIX: Use entrySet for efficiency.
for (Map.Entry<Integer, LinkedList<Integer>> entry : graph.entrySet()) {
if (!entry.getValue().isEmpty()) {
startNode = entry.getKey();
break;
}
}
if (startNode == -1) {
return true;
}
dfs(startNode, visited);
// FINAL FIX: Use entrySet for efficiency.
for (Map.Entry<Integer, LinkedList<Integer>> entry : graph.entrySet()) {
if (!entry.getValue().isEmpty() && !visited.contains(entry.getKey())) {
return false;
}
}
return true;
}
private void dfs(int u, Set<Integer> visited) {
visited.add(u);
if (graph.containsKey(u)) {
for (int v : graph.get(u)) {
if (!visited.contains(v)) {
dfs(v, visited);
}
}
}
}
}