123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128 |
- // Copyright 2022 gorse Project Authors
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- package heap
- import (
- "container/heap"
- "github.com/chewxy/math32"
- mapset "github.com/deckarep/golang-set/v2"
- "golang.org/x/exp/constraints"
- )
- type Elem[E any, W constraints.Ordered] struct {
- Value E
- Weight W
- }
- type _heap[T any, W constraints.Ordered] struct {
- elems []Elem[T, W]
- desc bool
- }
- func (e *_heap[T, W]) Len() int {
- return len(e.elems)
- }
- func (e *_heap[T, W]) Less(i, j int) bool {
- if e.desc {
- return e.elems[i].Weight > e.elems[j].Weight
- } else {
- return e.elems[i].Weight < e.elems[j].Weight
- }
- }
- func (e *_heap[T, W]) Swap(i, j int) {
- e.elems[i], e.elems[j] = e.elems[j], e.elems[i]
- }
- func (e *_heap[T, W]) Push(x interface{}) {
- it := x.(Elem[T, W])
- e.elems = append(e.elems, it)
- }
- func (e *_heap[T, W]) Pop() interface{} {
- old := e.elems
- item := e.elems[len(old)-1]
- e.elems = old[0 : len(old)-1]
- return item
- }
- // PriorityQueue represents the priority queue.
- type PriorityQueue struct {
- _heap[int32, float32]
- lookup mapset.Set[int32]
- }
- // NewPriorityQueue initializes an empty priority queue.
- func NewPriorityQueue(desc bool) *PriorityQueue {
- return &PriorityQueue{
- _heap: _heap[int32, float32]{desc: desc},
- lookup: mapset.NewSet[int32](),
- }
- }
- // Push inserts a new element into the queue. No action is performed on duplicate elements.
- func (p *PriorityQueue) Push(v int32, weight float32) {
- if math32.IsNaN(weight) {
- panic("NaN weight is forbidden")
- } else if !p.lookup.Contains(v) {
- newItem := Elem[int32, float32]{
- Value: v,
- Weight: weight,
- }
- heap.Push(&p._heap, newItem)
- p.lookup.Add(v)
- }
- }
- // Pop removes the element with the highest priority from the queue and returns it.
- // In case of an empty queue, an error is returned.
- func (p *PriorityQueue) Pop() (int32, float32) {
- item := heap.Pop(&p._heap).(Elem[int32, float32])
- return item.Value, item.Weight
- }
- func (p *PriorityQueue) Peek() (int32, float32) {
- return p.elems[0].Value, p.elems[0].Weight
- }
- func (p *PriorityQueue) Values() []int32 {
- values := make([]int32, 0, p.Len())
- for _, elem := range p.elems {
- values = append(values, elem.Value)
- }
- return values
- }
- func (p *PriorityQueue) Elems() []Elem[int32, float32] {
- return p.elems
- }
- func (p *PriorityQueue) Clone() *PriorityQueue {
- pq := NewPriorityQueue(p.desc)
- pq.elems = make([]Elem[int32, float32], p.Len())
- copy(pq.elems, p.elems)
- return pq
- }
- func (p *PriorityQueue) Reverse() *PriorityQueue {
- pq := NewPriorityQueue(!p.desc)
- pq.elems = make([]Elem[int32, float32], 0, p.Len())
- for _, elem := range p.elems {
- pq.Push(elem.Value, elem.Weight)
- }
- return pq
- }
|