Reputation: 9119
I took the full implementation of priority queue from go documentation. I want to remove elements if they satisfy some condition. So I should:
Like this:
for i, value := range pq{
if someCondtion{
heap.Remove(&pq, i)
}
}
Or for simplicity:
for i, value := range pq{
heap.Remove(&pq, i)
}
But it is not the safe way because there is an error:
panic: runtime error: index out of range
goroutine 1 [running]:
main.PriorityQueue.Swap(...)
main.(*PriorityQueue).Swap(0xc420088020, 0x2, 0x0)
container/heap.Remove(0x4c69a0, 0xc420088020, 0x2, 0xf, 0x0)
How can I properly do it? Here is an example https://play.golang.org/p/XrQdAJIbZPw
Upvotes: 1
Views: 885
Reputation: 301
assuming I have a PriorityQueue
struct the wraps the container/heap
calls and contain a queue
which implements heap.Interface
func (pq *PriorityQueue[T]) Remove(shouldRemove func(T) bool) {
tmpQueue := pq.queue[:0]
for _, element := range pq.queue{
if !shouldRemove(element) {
tmpQueue = append(tmpQueue, element)
}
}
// clear the rest of the queue to avoid memory leaks
var zero T
for i := len(tmpQueue); i < len(pq.queue); i++ {
pq.queue[i] = zero
}
pq.queue= tmpQueue
// re-heapify the queue
heap.Init(pq.queue)
}
the filtering code comes from: https://github.com/golang/go/wiki/SliceTricks#filtering-without-allocating
Upvotes: 0
Reputation: 5770
I think you are not using the correct data structure or the used data structure not correctly. The idea of a queue is to put items at the end for future processing and to take items from the beginning to process them.
If you do not want to process certain items, you could either filter them before queuing or filter when they are taken from the queue before processing.
Upvotes: 3
Reputation:
After every call to heap.Remove
the heap is reorganized. So the initial length of pq
gets smaller in every loop. You will reach the point when it is smaller than the current value of i
requires it to be.
If you manipulate pq
you must loop as it is done in the example:
for pq.Len() > 0 {
item := heap.Pop(&pq).(*Item)
fmt.Printf("%.2d:%s\n", item.priority, item.value)
}
see https://play.golang.org/p/Ayt4_zLo8FF
Upvotes: 3