-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathdijkstra.go
89 lines (71 loc) · 1.57 KB
/
dijkstra.go
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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
package graphs
import (
"container/heap"
"container/list"
"math"
)
type dijkstraNode[T Vertex] struct {
vertex T
distance float64
predecessor *dijkstraNode[T]
index int // Index of the node in the heap
}
type dijkstraPQ[T Vertex] []*dijkstraNode[T]
func (dpq dijkstraPQ[T]) Len() int {
return len(dpq)
}
func (dpq dijkstraPQ[T]) Less(i, j int) bool {
return dpq[i].distance < dpq[j].distance
}
func (dpq dijkstraPQ[T]) Swap(i, j int) {
dpq[i], dpq[j] = dpq[j], dpq[i]
dpq[i].index, dpq[j].index = i, j
}
func (dpq *dijkstraPQ[T]) Push(x interface{}) {
dn := x.(*dijkstraNode[T])
dn.index = len(*dpq)
*dpq = append(*dpq, dn)
}
func (dpq *dijkstraPQ[T]) Pop() interface{} {
n := len(*dpq)
node := (*dpq)[n-1]
*dpq = (*dpq)[0 : n-1]
return node
}
func Dijkstra[T Vertex](g *Graph[T], start, end T) *list.List {
pq := dijkstraPQ[T]{}
nodes := map[T]*dijkstraNode[T]{}
heap.Init(&pq)
g.EachVertex(func(v T, _ func()) {
dn := &dijkstraNode[T]{
vertex: v,
distance: math.Inf(1),
}
heap.Push(&pq, dn)
nodes[v] = dn
})
nodes[start].distance = 0
heap.Fix(&pq, nodes[start].index)
for pq.Len() > 0 {
v := heap.Pop(&pq).(*dijkstraNode[T])
g.EachHalfedge(v.vertex, func(he Halfedge[T], _ func()) {
dn := nodes[he.End]
if dn == nil {
return
}
if v.distance+he.Cost < dn.distance {
dn.distance = v.distance + he.Cost
dn.predecessor = v
heap.Fix(&pq, dn.index)
}
})
if v.vertex == end {
l := list.New()
for e := v; e != nil; e = e.predecessor {
l.PushFront(e.vertex)
}
return l
}
}
return nil
}