The heap
package expects that you provide an object that meets the heap.Interface
. So, in the example, both IntHeap
and PriorityQueue
are the objects that meet the interface. I think that the confusion is that most people would expect the example to work differently e.g.
q := NewMinimumPriorityQueue()
q.Push("A", 1)
q.Push("E", 5)
q.Push("D", 4)
q.Push("B", 2)
item := q.Pop() // giving A
To be able to achieve this, it needs 2 objects implemented:
- A store (heap) that meets
heap.Interface
- A priority queue
So the heap implementation for a min priority queue would be something like:
type element struct {
priority int
data any
index int
}
type store []*element
func (s *store) Len() int {
return len(*s)
}
func (s *store) Less(i, j int) bool {
h := *s
return h[i].priority < h[j].priority
}
func (s *store) Swap(i, j int) {
h := *s
h[j], h[i] = h[i], h[j]
h[i].index = i
h[j].index = j
}
func (s *store) Push(x any) {
h := *s
h = append(h, x.(*element))
*s = h
}
func (s *store) Pop() any {
h := *s
n := len(h)
if len(h) > 0 {
el := h[n-1]
*s = h[0 : n-1]
return el
}
return nil
}
The public min priority queue implementation:
type MinimumPriorityQueue struct {
store store
}
func NewMinimumPriorityQueue() *MinimumPriorityQueue {
q := &MinimumPriorityQueue{
store: make([]*element, 0),
}
heap.Init(&q.store)
return q
}
func (q *MinimumPriorityQueue) Push(data any, priority int) {
// append the element to the store
el := &element{
priority: priority,
data: data,
index: q.store.Len(),
}
heap.Push(&q.store, el)
// fix the store order
heap.Fix(&q.store, el.index)
}
func (q *MinimumPriorityQueue) Pop() any {
if q.Len() == 0 {
return nil
}
el := heap.Pop(&q.store)
if el == nil {
return nil
}
return el.(*element).data
}
Store the store
is an internal, low-level implementation that is used by the public MinimumPriorityQueue
.
container/heap
package in this post along with some example usage: tugberkugurlu.com/archive/… – Roehm