From f6f6d53b7836d212562692c568be0760c1550e49 Mon Sep 17 00:00:00 2001 From: Ivan Li Date: Wed, 30 Jan 2019 22:03:37 +0800 Subject: [PATCH] DFS topology sort --- .../ch43_topology_sort/GraphTopology.scala | 44 ++++++++++++++- .../GraphTopologyTest.scala | 56 +++++++++++++++++++ 2 files changed, 99 insertions(+), 1 deletion(-) diff --git a/scala/src/main/scala/ch43_topology_sort/GraphTopology.scala b/scala/src/main/scala/ch43_topology_sort/GraphTopology.scala index e942260..c7aaeb5 100644 --- a/scala/src/main/scala/ch43_topology_sort/GraphTopology.scala +++ b/scala/src/main/scala/ch43_topology_sort/GraphTopology.scala @@ -1,6 +1,7 @@ package ch43_topology_sort import scala.collection.mutable +import scala.collection.mutable.ArrayBuffer class GraphTopology(vertex: Int) { @@ -16,7 +17,7 @@ class GraphTopology(vertex: Int) { def topologySortByKahn(): Array[Int] = { val seq = new mutable.ArrayBuffer[Int]() - //inDgrees contains all the inDegree for a given node + //inDegrees contains all the inDegree for a given node val inDegrees = new Array[Int](vertex) for (i <- Range(0, vertex)) { for (j <- adjacency(i).indices) { @@ -53,6 +54,47 @@ class GraphTopology(vertex: Int) { seq.toArray } + + def topologySortByDFS(): Array[Int] = { + val inverseAdj = new Array[mutable.MutableList[Int]](vertex) + for (i <- Range(0, vertex)) { + inverseAdj(i) = new mutable.MutableList[Int]() + } + + //build the inverse adj + for (i <- Range(0, vertex)) { + for (j <- adjacency(i).indices) { + val index = adjacency(i).get(j).get + inverseAdj(index) += i + } + } + + val visited = new Array[Boolean](vertex) + val seq = new ArrayBuffer[Int]() + for (i <- Range(0, vertex)) { + if (!visited(i)) { + visited(i) = true + //call dfs + seq ++= dfs(i, inverseAdj, visited) + } + } + + seq.toArray + } + + def dfs(index: Int, inverseAdj: Array[mutable.MutableList[Int]], visited: Array[Boolean]): ArrayBuffer[Int] = { + val seq = new ArrayBuffer[Int]() + + for (i <- inverseAdj(index).indices) { + val sourceIndex = inverseAdj(index).get(i).get + if (!visited(sourceIndex)) { + visited(sourceIndex) = true + seq ++= dfs(sourceIndex, inverseAdj, visited) + } + } + seq += index + seq + } } diff --git a/scala/src/test/scala/ch43_topology_sort/GraphTopologyTest.scala b/scala/src/test/scala/ch43_topology_sort/GraphTopologyTest.scala index 96b0e9a..dfb2432 100644 --- a/scala/src/test/scala/ch43_topology_sort/GraphTopologyTest.scala +++ b/scala/src/test/scala/ch43_topology_sort/GraphTopologyTest.scala @@ -61,4 +61,60 @@ class GraphTopologyTest extends FlatSpec with Matchers { val seq = graphTopology.topologySortByKahn() seq.map(nodes(_)).mkString(",") should equal("a") } + + /* + a -> b + | | + \|/ \|/ + c -> d -> e + */ + it should "topologySortByDFS - 1" in { + val nodes = Array("a", "b", "c", "d", "e") + val graphTopology = new GraphTopology(nodes.length) + graphTopology.addEdge(0, 1) + graphTopology.addEdge(0, 2) + graphTopology.addEdge(1, 3) + graphTopology.addEdge(2, 3) + graphTopology.addEdge(3, 4) + + val seq = graphTopology.topologySortByDFS() + seq.map(nodes(_)).mkString(",") should equal("a,b,c,d,e") + } + + /* + a -> d --- + | | + \|/ \|/ + e -> c + */ + it should "topologySortByDFS - 2" in { + val nodes = Array("a", "b", "c", "d", "e") + val graphTopology = new GraphTopology(nodes.length) + graphTopology.addEdge(0, 3) + graphTopology.addEdge(3, 4) + graphTopology.addEdge(3, 2) + graphTopology.addEdge(4, 2) + + val seq = graphTopology.topologySortByDFS() + seq.map(nodes(_)).mkString(",") should equal("a,b,d,e,c") + } + + /* + a -> d <- b + | /|\ + \|/ | + e -> c + */ + it should "topologySortByDFS - 3" in { + val nodes = Array("a", "b", "c", "d", "e") + val graphTopology = new GraphTopology(nodes.length) + graphTopology.addEdge(0, 3) + graphTopology.addEdge(3, 4) + graphTopology.addEdge(4, 2) + graphTopology.addEdge(2, 1) + graphTopology.addEdge(1, 3) + + val seq = graphTopology.topologySortByKahn() + seq.map(nodes(_)).mkString(",") should equal("a") + } }