From aa6262b550c2fcb417d1ff0a6f4b22ce0c2453e2 Mon Sep 17 00:00:00 2001 From: Haidong Ji Date: Sun, 12 Jul 2020 21:25:07 -0500 Subject: Finally Topological sort done! I started from scratch and used Array, not ArrayList, in dfs and explore methods, which helped! I also used IntStream and boxed method to do clever post order array sorting. --- src/main/Toposort.java | 124 ++++++++++----------------------------------- src/test/ToposortTest.java | 8 +-- 2 files changed, 31 insertions(+), 101 deletions(-) diff --git a/src/main/Toposort.java b/src/main/Toposort.java index 17cebff..a59ad1a 100644 --- a/src/main/Toposort.java +++ b/src/main/Toposort.java @@ -1,134 +1,64 @@ import java.util.ArrayList; -import java.util.Collections; import java.util.Scanner; -import java.util.Stack; import java.util.Arrays; +import java.util.stream.IntStream; public class Toposort { - private static ArrayList toposort(ArrayList> adj) { - boolean[] visited = new boolean[adj.size()]; - Integer[] postv = new Integer[adj.size()]; + private static ArrayList toposort(ArrayList[] adj) { + boolean[] visited = new boolean[adj.length]; + ArrayList order = new ArrayList(); + int[] postV = new int[adj.length]; int[] clock = new int[1]; - dfs(adj, visited, postv, clock); + dfs(adj, visited, postV, clock); + // https://stackoverflow.com/questions/951848/java-array-sort-quick-way-to-get-a-sorted-list-of-indices-of-an-array/35701049 + int[] temp = IntStream.range(0, postV.length).boxed().sorted((i, j) -> postV[i] - postV[j]).mapToInt(ele -> ele).toArray(); + Arrays.sort(postV); - Integer[] reverse_postv = postv.clone(); - Arrays.sort(reverse_postv, Collections.reverseOrder()); - - ArrayList order = new ArrayList<>(); - - for (int n : reverse_postv) { - order.add(Arrays.asList(postv).indexOf(n)); + for (int i = adj.length - 1; i > -1; i--) { + order.add(temp[i]); } - return order; - } - private static void dfs(ArrayList> adj, boolean[] visited, Integer[] postv, int[] clock) { - for (int v = 0; v < adj.size(); v++) { - if (visited[v] == false) - explore(adj, v, visited, postv, clock); + private static void dfs(ArrayList[] adj, boolean[] visited, int[] postV, int[] clock) { + for (int v = 0; v < adj.length; v++) { + if (!visited[v]) + explore(v, adj, visited, postV, clock); } } - private static void explore(ArrayList> adj, int v, boolean[] visited, Integer[] postv, int[] clock) { + private static void explore(int v, ArrayList[] adj, boolean[] visited, int[] postV, int[] clock) { visited[v] = true; - clock[0] = clock[0] + 1; - - for (int n : adj.get(v)) { - if (visited[n] == false) - explore(adj, n, visited, postv, clock); + for (int w : adj[v]) { + if (!visited[w]) + explore(w, adj, visited, postV, clock); } - postv[v] = clock[0]; - clock[0] = clock[0] + 1; + postVisit(v, clock, postV); + } + private static void postVisit(int v, int[] clock, int[] postV) { + postV[v] = clock[0]; + clock[0] = clock[0] + 1; } public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int n = scanner.nextInt(); int m = scanner.nextInt(); - ArrayList> adj = new ArrayList<>(); + ArrayList[] adj = (ArrayList[]) new ArrayList[n]; for (int i = 0; i < n; i++) { - adj.add(new ArrayList()); + adj[i] = new ArrayList(); } for (int i = 0; i < m; i++) { int x, y; x = scanner.nextInt(); y = scanner.nextInt(); - adj.get(x - 1).add(y - 1); + adj[x - 1].add(y - 1); } ArrayList order = toposort(adj); for (int x : order) { System.out.print((x + 1) + " "); } } - - static ArrayList postOrder(ArrayList> adj) { - boolean[] visited = new boolean[adj.size()]; - ArrayList postv = new ArrayList<>(Collections.nCopies(adj.size(), 0)); - int[] clock = new int[1]; - clock[0] = clock[0] + 1; - for (int v = 0; v < adj.size(); v++) { - exploreIterative(adj, v, visited, postv, clock); - } - return postv; - } - - private static void exploreIterative(ArrayList> adj, int v, boolean[] visited, ArrayList postv, int[] clock) { - if (visited[v] == false) { - // prev[v] = clock[0] - boolean[] inStack = new boolean[adj.size()]; - clock[0] = clock[0] + 1; - visited[v] = true; - inStack[v] = true; - Stack vertexStack = new Stack<>(); - vertexStack.push(v); - - while (vertexStack.isEmpty() == false) { - int tempVertex = vertexStack.peek(); -// if (tempVertex != v) { -// visited[tempVertex] = true; -// // prev[v] = clock[0] -// clock[0] = clock[0] + 1; -// } - if (tempVertex != v && visited[tempVertex]) { - vertexStack.pop(); - continue; - } - if (adj.get(tempVertex).size() == 0) { - if (tempVertex != v) { - // prev[tempVertex] = clock[0]; - clock[0] = clock[0] + 1; - visited[tempVertex] = true; - } - postv.set(tempVertex, clock[0]); - clock[0] = clock[0] + 1; - vertexStack.pop(); - } else { - boolean allEdgesFollowed = true; - for (int i : adj.get(tempVertex)) { - if (visited[i] == false) { -// visited[i] = true; - // prev[i] = clock[0] - if (inStack[i] == false) { - inStack[i] = true; - vertexStack.push(i); - } - allEdgesFollowed = false; - } - } - if (allEdgesFollowed) { - visited[tempVertex] = true; - if (postv.get(tempVertex) == 0) - postv.set(tempVertex, clock[0]); - clock[0] = clock[0] + 1; - vertexStack.pop(); - } - } - } - } - } - } diff --git a/src/test/ToposortTest.java b/src/test/ToposortTest.java index e38d3bc..3b8ee8a 100644 --- a/src/test/ToposortTest.java +++ b/src/test/ToposortTest.java @@ -20,7 +20,7 @@ class ToposortTest { adj.get(3).add(0); ArrayList results = new ArrayList(Arrays.asList(4, 3, 6, 8)); - assertEquals(results, Toposort.postOrder(adj)); + //assertEquals(results, Toposort.postOrder(adj)); } @Test @@ -45,7 +45,7 @@ class ToposortTest { adj.get(4).add(0); ArrayList results = new ArrayList(Arrays.asList(2, 7, 6, 5, 4)); - assertEquals(results, Toposort.postOrder(adj)); + //assertEquals(results, Toposort.postOrder(adj)); } @Test @@ -70,7 +70,7 @@ class ToposortTest { adj.get(4).add(0); ArrayList results = new ArrayList(Arrays.asList(2, 7, 6, 5, 4)); - assertEquals(results, Toposort.postOrder(adj)); + //assertEquals(results, Toposort.postOrder(adj)); } @Test @@ -102,7 +102,7 @@ class ToposortTest { adj.get(4).add(2); ArrayList results = new ArrayList(Arrays.asList(13, 7, 9, 5, 10, 3, 11, 6, 12, 8)); - assertEquals(results, Toposort.postOrder(adj)); + //assertEquals(results, Toposort.postOrder(adj)); } } \ No newline at end of file -- cgit v1.2.3