forked from wangzheng0822/algo
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
42ecf5c
commit 1ac446f
Showing
3 changed files
with
159 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
package ch31_graph | ||
|
||
import scala.collection.mutable | ||
import scala.collection.mutable.ArrayBuffer | ||
import scala.util.control.Breaks._ | ||
|
||
class Graph(vertex: Array[String]) { | ||
|
||
require(vertex.nonEmpty, "nonEmpty vertex required") | ||
val adjacency = new Array[mutable.MutableList[String]](vertex.length) | ||
for (i <- Range(0, vertex.length)) { | ||
adjacency(i) = new mutable.MutableList[String]() | ||
} | ||
|
||
def addEdge(startNode: String, endNode: String): Unit = { | ||
adjacency(vertex.indexOf(startNode)) += endNode | ||
adjacency(vertex.indexOf(endNode)) += startNode | ||
} | ||
|
||
def getEdges(node: String): Array[String] = { | ||
adjacency(vertex.indexOf(node)).toArray | ||
} | ||
|
||
def breathFirstSearch(startNode: String, destNode: String): Option[Array[String]] = { | ||
var result: Option[Array[String]] = None | ||
val queue = new mutable.Queue[String]() | ||
val visited = new mutable.HashSet[String]() | ||
val explored = new ArrayBuffer[String]() | ||
|
||
//put starting node into the queue | ||
queue += startNode | ||
breakable { | ||
while (queue.nonEmpty) { | ||
val node = queue.dequeue() | ||
if (!visited.contains(node)) { | ||
explored += node | ||
visited += node | ||
|
||
if (node.equals(destNode)) { | ||
result = Some(explored.toArray) | ||
break | ||
} | ||
queue ++= adjacency(vertex.indexOf(node)) | ||
} | ||
|
||
} | ||
} | ||
|
||
result | ||
} | ||
|
||
def depthFirstSearch(startNode: String, destNode: String): Option[Array[String]] = { | ||
var found = false | ||
val visited = new mutable.HashSet[String]() | ||
val explored = new ArrayBuffer[String]() | ||
|
||
def _dfs(start: String): Unit = { | ||
if (found) { | ||
return | ||
} | ||
if (!visited.contains(start)) { | ||
visited += start | ||
explored += start | ||
val destsForStart: mutable.MutableList[String] = adjacency(vertex.indexOf(start)) | ||
|
||
breakable { | ||
for (i <- destsForStart.indices) { | ||
val node = destsForStart(i) | ||
if (node.equals(destNode)) { | ||
found = true | ||
if (!explored.contains(node)) { | ||
explored += node | ||
} | ||
break() | ||
} | ||
_dfs(node) | ||
} | ||
} | ||
} | ||
} | ||
|
||
_dfs(startNode) | ||
if (found) { | ||
Some(explored.toArray) | ||
} else { | ||
None | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
package ch31_graph | ||
|
||
import org.scalatest.{FlatSpec, Matchers} | ||
|
||
class GraphTest extends FlatSpec with Matchers { | ||
|
||
/* | ||
0 - 1 - 2 | ||
| | | | ||
3 - 4 - 5 | ||
| | | ||
6 - 7 | ||
*/ | ||
|
||
behavior of "GraphTest" | ||
|
||
def initGraph: Graph = { | ||
val num = 8 | ||
val vertex = new Array[String](num) | ||
for (i <- Range(0, num)) { | ||
vertex(i) = i.toString | ||
} | ||
val graph = new Graph(vertex) | ||
|
||
graph.addEdge("0", "1") | ||
graph.addEdge("1", "2") | ||
graph.addEdge("0", "3") | ||
graph.addEdge("1", "4") | ||
graph.addEdge("2", "5") | ||
graph.addEdge("3", "4") | ||
graph.addEdge("4", "5") | ||
graph.addEdge("4", "6") | ||
graph.addEdge("5", "7") | ||
graph.addEdge("6", "7") | ||
graph | ||
} | ||
|
||
it should "construct the graph" in { | ||
val graph: Graph = initGraph | ||
|
||
graph.getEdges("0").sorted should equal(Array("1", "3")) | ||
graph.getEdges("1").sorted should equal(Array("0", "2", "4")) | ||
graph.getEdges("2").sorted should equal(Array("1", "5")) | ||
graph.getEdges("3").sorted should equal(Array("0", "4")) | ||
graph.getEdges("4").sorted should equal(Array("1", "3", "5", "6")) | ||
graph.getEdges("5").sorted should equal(Array("2", "4", "7")) | ||
graph.getEdges("6").sorted should equal(Array("4", "7")) | ||
graph.getEdges("7").sorted should equal(Array("5", "6")) | ||
} | ||
|
||
it should "do breath first search in graph" in { | ||
val graph: Graph = initGraph | ||
graph.breathFirstSearch("0", "4").get should equal(Array("0", "1", "3", "2", "4")) | ||
graph.breathFirstSearch("1", "5").get should equal(Array("1", "0", "2", "4", "3", "5")) | ||
assert(graph.breathFirstSearch("1", "8").isEmpty) | ||
} | ||
|
||
it should "do depth first search in graph" in { | ||
val graph: Graph = initGraph | ||
graph.depthFirstSearch("0", "4").get should equal(Array("0", "1", "2", "5", "4")) | ||
graph.depthFirstSearch("1", "5").get should equal(Array("1", "0", "3", "4", "5")) | ||
assert(graph.depthFirstSearch("1", "8").isEmpty) | ||
} | ||
} |