pq.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. // Copyright 2022 gorse Project Authors
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package heap
  15. import (
  16. "container/heap"
  17. "github.com/chewxy/math32"
  18. mapset "github.com/deckarep/golang-set/v2"
  19. "golang.org/x/exp/constraints"
  20. )
  21. type Elem[E any, W constraints.Ordered] struct {
  22. Value E
  23. Weight W
  24. }
  25. type _heap[T any, W constraints.Ordered] struct {
  26. elems []Elem[T, W]
  27. desc bool
  28. }
  29. func (e *_heap[T, W]) Len() int {
  30. return len(e.elems)
  31. }
  32. func (e *_heap[T, W]) Less(i, j int) bool {
  33. if e.desc {
  34. return e.elems[i].Weight > e.elems[j].Weight
  35. } else {
  36. return e.elems[i].Weight < e.elems[j].Weight
  37. }
  38. }
  39. func (e *_heap[T, W]) Swap(i, j int) {
  40. e.elems[i], e.elems[j] = e.elems[j], e.elems[i]
  41. }
  42. func (e *_heap[T, W]) Push(x interface{}) {
  43. it := x.(Elem[T, W])
  44. e.elems = append(e.elems, it)
  45. }
  46. func (e *_heap[T, W]) Pop() interface{} {
  47. old := e.elems
  48. item := e.elems[len(old)-1]
  49. e.elems = old[0 : len(old)-1]
  50. return item
  51. }
  52. // PriorityQueue represents the priority queue.
  53. type PriorityQueue struct {
  54. _heap[int32, float32]
  55. lookup mapset.Set[int32]
  56. }
  57. // NewPriorityQueue initializes an empty priority queue.
  58. func NewPriorityQueue(desc bool) *PriorityQueue {
  59. return &PriorityQueue{
  60. _heap: _heap[int32, float32]{desc: desc},
  61. lookup: mapset.NewSet[int32](),
  62. }
  63. }
  64. // Push inserts a new element into the queue. No action is performed on duplicate elements.
  65. func (p *PriorityQueue) Push(v int32, weight float32) {
  66. if math32.IsNaN(weight) {
  67. panic("NaN weight is forbidden")
  68. } else if !p.lookup.Contains(v) {
  69. newItem := Elem[int32, float32]{
  70. Value: v,
  71. Weight: weight,
  72. }
  73. heap.Push(&p._heap, newItem)
  74. p.lookup.Add(v)
  75. }
  76. }
  77. // Pop removes the element with the highest priority from the queue and returns it.
  78. // In case of an empty queue, an error is returned.
  79. func (p *PriorityQueue) Pop() (int32, float32) {
  80. item := heap.Pop(&p._heap).(Elem[int32, float32])
  81. return item.Value, item.Weight
  82. }
  83. func (p *PriorityQueue) Peek() (int32, float32) {
  84. return p.elems[0].Value, p.elems[0].Weight
  85. }
  86. func (p *PriorityQueue) Values() []int32 {
  87. values := make([]int32, 0, p.Len())
  88. for _, elem := range p.elems {
  89. values = append(values, elem.Value)
  90. }
  91. return values
  92. }
  93. func (p *PriorityQueue) Elems() []Elem[int32, float32] {
  94. return p.elems
  95. }
  96. func (p *PriorityQueue) Clone() *PriorityQueue {
  97. pq := NewPriorityQueue(p.desc)
  98. pq.elems = make([]Elem[int32, float32], p.Len())
  99. copy(pq.elems, p.elems)
  100. return pq
  101. }
  102. func (p *PriorityQueue) Reverse() *PriorityQueue {
  103. pq := NewPriorityQueue(!p.desc)
  104. pq.elems = make([]Elem[int32, float32], 0, p.Len())
  105. for _, elem := range p.elems {
  106. pq.Push(elem.Value, elem.Weight)
  107. }
  108. return pq
  109. }