65 lines
1.5 KiB
C
65 lines
1.5 KiB
C
/* rizin - LGPL - Copyright 2017-2018 - maskray */
|
|
|
|
#include "rz_binheap.h"
|
|
|
|
static inline void _heap_down(RzBinHeap *h, size_t i, void *x) {
|
|
size_t j;
|
|
for (; j = i * 2 + 1, j < h->a.v.len; i = j) {
|
|
if (j + 1 < h->a.v.len && h->cmp(rz_pvector_at(&h->a, j + 1), rz_pvector_at(&h->a, j)) < 0) {
|
|
j++;
|
|
}
|
|
if (h->cmp(rz_pvector_at(&h->a, j), x) >= 0) {
|
|
break;
|
|
}
|
|
rz_pvector_set(&h->a, i, rz_pvector_at(&h->a, j));
|
|
}
|
|
if (i < h->a.v.len) {
|
|
rz_pvector_set(&h->a, i, x);
|
|
}
|
|
}
|
|
|
|
static inline void _heap_up(RzBinHeap *h, size_t i, void *x) {
|
|
size_t j;
|
|
for (; i && (j = (i - 1) >> 1, h->cmp(x, rz_pvector_at(&h->a, j)) < 0); i = j) {
|
|
rz_pvector_set(&h->a, i, rz_pvector_at(&h->a, j));
|
|
}
|
|
rz_pvector_set(&h->a, i, x);
|
|
}
|
|
|
|
RZ_API void rz_binheap_clear(RzBinHeap *h) {
|
|
rz_pvector_clear(&h->a);
|
|
}
|
|
|
|
RZ_API void rz_binheap_init(RzBinHeap *h, RzPVectorComparator cmp) {
|
|
rz_pvector_init(&h->a, NULL);
|
|
h->cmp = cmp;
|
|
}
|
|
|
|
RZ_API void rz_binheap_free(RzBinHeap *h) {
|
|
rz_binheap_clear(h);
|
|
free(h);
|
|
}
|
|
|
|
RZ_API RzBinHeap *rz_binheap_new(RzPVectorComparator cmp) {
|
|
RzBinHeap *h = RZ_NEW(RzBinHeap);
|
|
if (!h) {
|
|
return NULL;
|
|
}
|
|
rz_pvector_init(&h->a, NULL);
|
|
h->cmp = cmp;
|
|
return h;
|
|
}
|
|
|
|
RZ_API void *rz_binheap_pop(RzBinHeap *h) {
|
|
void *ret = rz_pvector_at(&h->a, 0);
|
|
_heap_down(h, 0, rz_pvector_pop(&h->a));
|
|
return ret;
|
|
}
|
|
|
|
RZ_API bool rz_binheap_push(RzBinHeap *h, void *x) {
|
|
if (!rz_pvector_push(&h->a, NULL)) {
|
|
return false;
|
|
}
|
|
_heap_up(h, h->a.v.len - 1, x);
|
|
return true;
|
|
}
|