Skip to content

Instantly share code, notes, and snippets.

@enriqueb721
Last active July 20, 2019 23:53
Show Gist options
  • Save enriqueb721/b3e25c28c9d7a9dd7a8745f6c615c6d8 to your computer and use it in GitHub Desktop.
Save enriqueb721/b3e25c28c9d7a9dd7a8745f6c615c6d8 to your computer and use it in GitHub Desktop.
Go concurrent priority queue / heap
package main
import "sync"
type item struct {
value interface{}
priority int
}
type nHeap struct {
sync.RWMutex
items []*item
itemsCount int
comparator func(int, int) bool
}
func newItem(value interface{}, priority int) *item {
return &item{
value: value,
priority: priority,
}
}
func newnHeap(maxOrd bool) *nHeap {
var cmp func(int, int) bool
cmp = max
if !maxOrd {
cmp = min
}
items := make([]*item, 1)
items[0] = nil
return &nHeap{
items: items,
itemsCount: 0,
comparator: cmp,
}
}
func (h *nHeap) Push(value interface{}, priority int) {
item := newItem(value, priority)
h.Lock()
defer h.Unlock()
h.items = append(h.items, item)
h.itemsCount++
h.swim(h.threadSize())
}
func (h *nHeap) Pop() interface{} {
h.Lock()
defer h.Unlock()
if h.threadSize() < 1 {
return nil
}
max := h.items[1]
h.swap(1, h.threadSize())
h.items = h.items[0:h.threadSize()]
h.itemsCount--
h.sink(1)
return max.value
}
func (h *nHeap) Size() int {
h.RLock()
defer h.RUnlock()
return h.threadSize()
}
func (h *nHeap) Empty() bool {
h.RLock()
defer h.RUnlock()
return h.threadSize() == 0
}
func (h *nHeap) threadSize() int {
return h.itemsCount
}
func (h *nHeap) less(i, j int) bool {
return h.comparator(h.items[i].priority, h.items[j].priority)
}
func (h *nHeap) swap(i, j int) {
h.items[i], h.items[j] = h.items[j], h.items[i]
}
func (h *nHeap) swim(k int) {
for k > 1 && h.less(k/2, k) {
h.swap(k/2, k)
k = k / 2
}
}
func (h *nHeap) sink(k int) {
for 2*k <= h.threadSize() {
j := 2 * k
if j < h.threadSize() && h.less(j, j+1) {
j++
}
if !h.less(k, j) {
break
}
h.swap(k, j)
k = j
}
}
func mai() {
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment