Skip to content

Instantly share code, notes, and snippets.

@gclaramunt
Created December 19, 2008 02:20
Show Gist options
  • Save gclaramunt/37766 to your computer and use it in GitHub Desktop.
Save gclaramunt/37766 to your computer and use it in GitHub Desktop.
Dijkstra shortest path - my first Scala program
package dfs2;
abstract class Graph {
type Edge
type Node <: NodeIntf
abstract class NodeIntf {
def connectWith(node: Node): Edge
}
def nodes: Set[Node]
def edges: Set[Edge]
def addNode: Node
}
abstract class DirectedGraph extends Graph {
type Edge <: EdgeImpl
class EdgeImpl(origin: Node, dest: Node) {
def from = origin
def to = dest
}
class NodeImpl extends NodeIntf {
self: Node =>
def connectWith(node: Node): Edge = {
val edge = newEdge(this, node)
edges = edges + edge
edge
}
}
protected def newNode: Node
protected def newEdge(from: Node, to: Node): Edge
var nodes: Set[Node] =Set()
var edges: Set[Edge] =Set()
def addNode: Node = {
val node = newNode
nodes = nodes + node
node
}
}
trait Weight {
var weight= Float.PositiveInfinity
}
import scala.collection.mutable.PriorityQueue;
class DfsGraph extends DirectedGraph {
class DfsNode extends NodeImpl with Weight with Ordered[DfsNode]{
var previous: DfsNode = _
var label:String = _
var nodeEdges: Set[Edge] = Set()
override def connectWith(node: Node): Edge = {
val newEdge=super.connectWith(node)
nodeEdges = nodeEdges + newEdge
newEdge
}
def -->(n2:Node):DfsEdge =connectWith(n2)
override def toString()= label+ " w:"+weight
def compare(y: Node): Int = this.weight.compare(y.weight)
}
class DfsEdge(origin:Node, dest:Node) extends EdgeImpl(origin, dest) with Weight {
override def toString()= from.label+"-->"+to.label+" w:"+weight
}
def addNewNode(l:String):Node={
val newNode=super.addNode
newNode.label=l
newNode
}
type Node= DfsNode
type Edge= DfsEdge
protected def newEdge(from: Node, to: Node): Edge = new DfsEdge(from,to)
protected def newNode: Node = new DfsNode
}
class DijkstraSPGraph extends DfsGraph {
class PQNode extends DfsNode {
override def compare(y: Node): Int = -super.compare(y)
}
override protected def newNode: Node = new PQNode
def shortestPath(start: DfsNode, end: DfsNode) = {
val unvisited=new PriorityQueue[Node]()
unvisited++=(nodes)
start.weight=0
while (!unvisited.isEmpty) {
val vertx=unvisited.dequeue
for (v <- vertx.nodeEdges if canImprove(v)){
unvisited+improveDistance(v)
}
}
}
def canImprove(a:Edge)=(a.from.weight+a.weight< a.to.weight)
def improveDistance(a:Edge) ={
val v=a.to
v.weight=a.from.weight+a.weight
v.previous=a.from
v
}
def pathToStart(end:DfsNode):List[DfsNode] = {
if (end == null)
Nil
else
end :: pathToStart(end.previous)
}
}
object Example extends Application {
val graph = new DijkstraSPGraph
val n1=graph addNewNode "start"
val n2=graph addNewNode "n2"
val n3=graph addNewNode "n3"
val n4=graph addNewNode "n4"
val n5=graph addNewNode "n5"
val n6=graph addNewNode "end"
graph addNewNode "alone"
n1-->n2 weight=2
n1-->n3 weight=1
n2-->n4 weight=1
n3-->n4 weight=3
n2-->n5 weight=1
n4-->n6 weight=1
n5-->n6 weight=3
n1-->n6 weight=7
n1-->n4 weight=10
graph.shortestPath(n1,n6)
println("Path")
graph.pathToStart(n6).reverse.map(println(_))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment