forked from sagivo/algorithms
-
Notifications
You must be signed in to change notification settings - Fork 0
/
dijkstra.rb
57 lines (53 loc) · 1.34 KB
/
dijkstra.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#Dijkstra's_algorithm
#source: http://rosettacode.org/wiki/Dijkstra's_algorithm#Ruby
class Graph
Vertex = Struct.new(:name, :neighbours, :dist, :prev)
def initialize(graph)
@vertices = Hash.new{|h,k| h[k]=Vertex.new(k,[],Float::INFINITY)}
@edges = {}
graph.each do |(v1, v2, dist)|
@vertices[v1].neighbours << v2
@vertices[v2].neighbours << v1
@edges[[v1, v2]] = @edges[[v2, v1]] = dist
end
@dijkstra_source = nil
end
def dijkstra(source)
return if @dijkstra_source == source
q = @vertices.values
q.each do |v|
v.dist = Float::INFINITY
v.prev = nil
end
@vertices[source].dist = 0
until q.empty?
u = q.min_by {|vertex| vertex.dist}
break if u.dist == Float::INFINITY
q.delete(u)
u.neighbours.each do |v|
vv = @vertices[v]
if q.include?(vv)
alt = u.dist + @edges[[u.name, v]]
if alt < vv.dist
vv.dist = alt
vv.prev = u.name
end
end
end
end
@dijkstra_source = source
end
def shortest_path(source, target)
dijkstra(source)
path = []
u = target
while u
path.unshift(u)
u = @vertices[u].prev
end
return path, @vertices[target].dist
end
def to_s
"#<%s vertices=%p edges=%p>" % [self.class.name, @vertices.values, @edges]
end
end