User:Margusmartsepp/Contributions/Java/Utils.java: Difference between revisions

no edit summary
No edit summary
No edit summary
 
(One intermediate revision by the same user not shown)
Line 45:
}
 
/** <p>
* <p>
* <b>Topological sort</b> solves a problem of - finding a linear ordering
* of the vertices of <i>V</i> such that for each edge <i>(i, j) ∈ E</i>,
Line 56 ⟶ 55:
* href="http://en.wikipedia.org/wiki/Topological_sort#Algorithms" > Kahn's
* pseudo code</a> and traverses over vertices as they are returned by input
* map. Leaf nodes can have null or empty values. This method assumes, that
* input is valid DAG, so if cyclic dependency is detected, error is thrown.
* tSortFix is a fix to remove self dependencies and add missing leaf nodes.
* </p>
*
* <pre>
* // InputFor input with elements:
* { F1=[F2, F3, F4], F10=[F7, F4], F11=[F4], F2=[F3, F8, F4], F3=[F6],
* F4=null, F5=[F6, F4], F6=[F7, F8, F4], F7=[F4], F8=[F4], F9=[F4]}
*
* // Output based on input map type:
* HashMap: [F4, F11, F8, F9, F7, F10, F6, F5, F3, F2, F1]
* TreeMap: [F4, F11, F7, F8, F9, F10, F6, F3, F5, F2, F1]
Line 74 ⟶ 75:
* {@link java.util.HashMap HashMap} elements.
*
* @return Linear ordering of input nodes. If input map contains a
* @throws Exception
* prerequisite that is undefined orThrown when cyclic dependency is detected, error message also
* then empty ArrayList will be returned.
* contains elements in cycle.
*
*/
public static <T> ArrayList<T> tSort(java.util.Map<T, ArrayList<T>> g) {
throws Exception
T n; // Current element.
/**
ArrayList<T> L = /* Answer */
* @param L
new ArrayList<T>(g.size());
* Answer.
java.util.HashSet<T> V = /* ! Visited elements */
* @param S
new java.util.HashSet<T>();
* Not visited leaf vertices.
java.util.Queue<T> S = /* ! Visited leaf nodes */
* @param V
new java.util.concurrent.LinkedBlockingDeque<T>();
* Visited vertices.
* @param P
* Defined vertices.
* @param n
T n;* // Current element.
*/
{
java.util.ArrayList<T> L = new ArrayList<T>(g.size());
java.util.Queue<T> S = new java.util.concurrent.LinkedBlockingDeque<T>();
java.util.HashSet<T> V = /*new ! Visited elementsjava.util.HashSet<T>(), */
P = new java.util.HashSet<T>();
for (T t : P.addAll(g.keySet());
T n;
 
// Find leaf nodes.
for (T t : g.keySet()P)
if (g.get(t) == null || g.get(t).isEmpty())
S.add(t);
 
// Visit all leaf nodes. Build result from vertices, that are visited
// for the first time. Add vertices to not visited leaf vertices S, if
while (!S.isEmpty()) {
// containedit contains current element n, addan all of it's tovalues leafare nodesvisited.
// First time seeing this leaf node?
if (V.add(n = while (!S.pollisEmpty())) {
L if (V.add(n = S.poll()));
L.add(n);
for (T t : g.keySet())
if (g.get(t) != null && !g.get(t).isEmpty() && !V.contains(t)
if (g.get(t) != null && V.containsAll(g.get(t)))
S.add(t);
}
 
// Return result.
// If any vertex contains only visited vertices and
if (!L.containsAll(g.keySet()P))
// contained current element n, add it to leaf nodes.
return L;
for (T t : g.keySet())
 
if (g.get(t) != null && V.containsAll(g.get(t))
// Throw exception.
&& !V.contains(t))
StringBuilder sb = new StringBuilder(
S.add(t);
"\nInvalid DAG: a cyclic dependency detected :\n");
}
for (T t : P)
&& if (!VL.contains(t))
sb.append(t).append(" ");
throw new Exception(sb.append("\n").toString());
}
 
/**
* Method removes self dependencies and adds missing leaf nodes.
* <p>
* @param g
* <a href="http://en.wikipedia.org/wiki/Directed_acyclic_graph"
* > Directed Acyclic Graph</a>, where vertices are stored as
* {@link java.util.HashMap HashMap} elements.
*/
public static <T> void tSortFix(java.util.Map<T, ArrayList<T>> g) {
java.util.ArrayList<T> tmp;
java.util.HashSet<T> P = new java.util.HashSet<T>();
P.addAll(g.keySet());
 
for (T t : P)
// Return empty ArrayList if input is not valid DAG.
if (g.get(t) != null || !g.get(t).isEmpty()) {
if (!L.containsAll(g.keySet()))
(tmp = g.get(t)).remove(t);
return new ArrayList<T>(0);
for (T m : tmp)
return L;
if (!P.contains(m))
return g.put(m, new ArrayList<T>(0));
}
}