-
Notifications
You must be signed in to change notification settings - Fork 0
/
priorityqueue.go
70 lines (59 loc) · 1.59 KB
/
priorityqueue.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
// Deprecated: chansort has now moved to github.com/jamesrom/order/chansort
package priorityqueue
import (
"constraints"
hp "container/heap"
"sync"
)
type PriorityQueue[T any] struct {
h heap[T]
mtx sync.RWMutex
}
type Prioritizable interface {
Priority() int
}
// New - highest priority / descending order
func New[T Prioritizable](items ...T) *PriorityQueue[T] {
greater := func(i, j T) bool {
return i.Priority() > j.Priority()
}
return NewWithComparator(greater, items...)
}
// NewWithOrderable - highest priority / descending order
func NewWithOrderable[T constraints.Ordered](items ...T) *PriorityQueue[T] {
greater := func(a, b T) bool { return a > b }
return NewWithComparator(greater, items...)
}
// Less must describe a transitive ordering:
// - if both Less(i, j) and Less(j, k) are true, then Less(i, k) must be true as well.
// - if both Less(i, j) and Less(j, k) are false, then Less(i, k) must be false as well.
type Less[T any] func(T, T) bool
// NewWithComparator - order defined by a custom less function
func NewWithComparator[T any](fn Less[T], items ...T) *PriorityQueue[T] {
h := heap[T]{
elements: items,
less: fn,
}
hp.Init(&h)
return &PriorityQueue[T]{h: h}
}
func (p *PriorityQueue[T]) Push(x T) {
p.mtx.Lock()
defer p.mtx.Unlock()
hp.Push(&p.h, x)
}
func (p *PriorityQueue[T]) Pop() T {
p.mtx.Lock()
defer p.mtx.Unlock()
return hp.Pop(&p.h).(T)
}
func (p *PriorityQueue[T]) Peek() T {
p.mtx.RLock()
defer p.mtx.RUnlock()
return p.h.elements[0]
}
func (p *PriorityQueue[T]) Len() int {
p.mtx.RLock()
defer p.mtx.RUnlock()
return len(p.h.elements)
}