|
1 | 1 | package graph |
2 | 2 |
|
3 | | -import ( |
4 | | - "container/heap" |
5 | | -) |
6 | | - |
7 | 3 | type prioQueue struct { |
8 | 4 | heap []int // vertices in heap order |
9 | 5 | index []int // index of each vertex in the heap |
10 | 6 | cost []int64 |
11 | 7 | } |
12 | 8 |
|
13 | | -func emptyQueue(cost []int64) *prioQueue { |
| 9 | +func emptyPrioQueue(cost []int64) *prioQueue { |
14 | 10 | return &prioQueue{ |
15 | 11 | index: make([]int, len(cost)), |
16 | 12 | cost: cost, |
17 | 13 | } |
18 | 14 | } |
19 | 15 |
|
20 | | -func newQueue(cost []int64) *prioQueue { |
| 16 | +func newPrioQueue(cost []int64) *prioQueue { |
21 | 17 | n := len(cost) |
22 | | - h := &prioQueue{ |
| 18 | + q := &prioQueue{ |
23 | 19 | heap: make([]int, n), |
24 | 20 | index: make([]int, n), |
25 | 21 | cost: cost, |
26 | 22 | } |
27 | | - for i := range h.heap { |
28 | | - h.heap[i] = i |
29 | | - h.index[i] = i |
| 23 | + for i := range q.heap { |
| 24 | + q.heap[i] = i |
| 25 | + q.index[i] = i |
30 | 26 | } |
31 | | - return h |
| 27 | + return q |
32 | 28 | } |
33 | 29 |
|
34 | | -func (m *prioQueue) Len() int { return len(m.heap) } |
| 30 | +// Len returns the number of elements in the queue. |
| 31 | +func (q *prioQueue) Len() int { |
| 32 | + return len(q.heap) |
| 33 | +} |
35 | 34 |
|
36 | | -func (m *prioQueue) Less(i, j int) bool { |
37 | | - return m.cost[m.heap[i]] < m.cost[m.heap[j]] |
| 35 | +// Push pushes v onto the queue. |
| 36 | +// The time complexity is O(log n) where n = q.Len(). |
| 37 | +func (q *prioQueue) Push(v int) { |
| 38 | + n := q.Len() |
| 39 | + q.heap = append(q.heap, v) |
| 40 | + q.index[v] = n |
| 41 | + q.up(n) |
38 | 42 | } |
39 | 43 |
|
40 | | -func (m *prioQueue) Swap(i, j int) { |
41 | | - m.heap[i], m.heap[j] = m.heap[j], m.heap[i] |
42 | | - m.index[m.heap[i]] = i |
43 | | - m.index[m.heap[j]] = j |
| 44 | +// Pop removes the minimum element from the queue and returns it. |
| 45 | +// The time complexity is O(log n) where n = q.Len(). |
| 46 | +func (q *prioQueue) Pop() int { |
| 47 | + n := q.Len() - 1 |
| 48 | + q.swap(0, n) |
| 49 | + q.down(0, n) |
| 50 | + |
| 51 | + v := q.heap[n] |
| 52 | + q.index[v] = -1 |
| 53 | + q.heap = q.heap[:n] |
| 54 | + return v |
44 | 55 | } |
45 | 56 |
|
46 | | -func (pq *prioQueue) Push(x interface{}) { |
47 | | - n := len(pq.heap) |
48 | | - v := x.(int) |
49 | | - pq.heap = append(pq.heap, v) |
50 | | - pq.index[v] = n |
| 57 | +// Contains tells whether v is in the queue. |
| 58 | +func (q *prioQueue) Contains(v int) bool { |
| 59 | + return q.index[v] >= 0 |
51 | 60 | } |
52 | 61 |
|
53 | | -func (m *prioQueue) Pop() interface{} { |
54 | | - n := len(m.heap) - 1 |
55 | | - v := m.heap[n] |
56 | | - m.index[v] = -1 |
57 | | - m.heap = m.heap[:n] |
58 | | - return v |
| 62 | +// Fix re-establishes the ordering after the cost for v has changed. |
| 63 | +// The time complexity is O(log n) where n = q.Len(). |
| 64 | +func (q *prioQueue) Fix(v int) { |
| 65 | + if i := q.index[v]; !q.down(i, q.Len()) { |
| 66 | + q.up(i) |
| 67 | + } |
59 | 68 | } |
60 | 69 |
|
61 | | -func (m *prioQueue) Update(v int) { |
62 | | - heap.Fix(m, m.index[v]) |
| 70 | +func (q *prioQueue) less(i, j int) bool { |
| 71 | + return q.cost[q.heap[i]] < q.cost[q.heap[j]] |
63 | 72 | } |
64 | 73 |
|
65 | | -func (m *prioQueue) Contains(v int) bool { |
66 | | - return m.index[v] >= 0 |
| 74 | +func (q *prioQueue) swap(i, j int) { |
| 75 | + q.heap[i], q.heap[j] = q.heap[j], q.heap[i] |
| 76 | + q.index[q.heap[i]] = i |
| 77 | + q.index[q.heap[j]] = j |
| 78 | +} |
| 79 | + |
| 80 | +func (q *prioQueue) up(j int) { |
| 81 | + for { |
| 82 | + i := (j - 1) / 2 // parent |
| 83 | + if i == j || !q.less(j, i) { |
| 84 | + break |
| 85 | + } |
| 86 | + q.swap(i, j) |
| 87 | + j = i |
| 88 | + } |
| 89 | +} |
| 90 | + |
| 91 | +func (q *prioQueue) down(i0, n int) bool { |
| 92 | + i := i0 |
| 93 | + for { |
| 94 | + j1 := 2*i + 1 |
| 95 | + if j1 >= n || j1 < 0 { // j1 < 0 after int overflow |
| 96 | + break |
| 97 | + } |
| 98 | + j := j1 // left child |
| 99 | + if j2 := j1 + 1; j2 < n && q.less(j2, j1) { |
| 100 | + j = j2 // = 2*i + 2 // right child |
| 101 | + } |
| 102 | + if !q.less(j, i) { |
| 103 | + break |
| 104 | + } |
| 105 | + q.swap(i, j) |
| 106 | + i = j |
| 107 | + } |
| 108 | + return i > i0 |
67 | 109 | } |
0 commit comments