Last active
July 20, 2019 23:53
-
-
Save enriqueb721/b3e25c28c9d7a9dd7a8745f6c615c6d8 to your computer and use it in GitHub Desktop.
Go concurrent priority queue / heap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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