|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include <config.h> |
|
|
|
|
|
#include "heap.h" |
|
|
#include "stdlib--.h" |
|
|
#include "xalloc.h" |
|
|
|
|
|
static int heap_default_compare (void const *, void const *); |
|
|
static void heapify_down (void **, idx_t, idx_t, |
|
|
int (*) (void const *, void const *)); |
|
|
static void heapify_up (void **, idx_t, |
|
|
int (*) (void const *, void const *)); |
|
|
|
|
|
struct heap |
|
|
{ |
|
|
void **array; |
|
|
idx_t capacity; |
|
|
idx_t count; |
|
|
int (*compare) (void const *, void const *); |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
struct heap * |
|
|
heap_alloc (int (*compare) (void const *, void const *), idx_t n_reserve) |
|
|
{ |
|
|
struct heap *heap = xmalloc (sizeof *heap); |
|
|
|
|
|
if (n_reserve == 0) |
|
|
n_reserve = 1; |
|
|
|
|
|
heap->array = xnmalloc (n_reserve, sizeof *(heap->array)); |
|
|
|
|
|
heap->array[0] = nullptr; |
|
|
heap->capacity = n_reserve; |
|
|
heap->count = 0; |
|
|
heap->compare = compare ? compare : heap_default_compare; |
|
|
|
|
|
return heap; |
|
|
} |
|
|
|
|
|
|
|
|
static int |
|
|
heap_default_compare (void const *a, void const *b) |
|
|
{ |
|
|
return 0; |
|
|
} |
|
|
|
|
|
|
|
|
void |
|
|
heap_free (struct heap *heap) |
|
|
{ |
|
|
free (heap->array); |
|
|
free (heap); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
int |
|
|
heap_insert (struct heap *heap, void *item) |
|
|
{ |
|
|
if (heap->capacity - 1 <= heap->count) |
|
|
heap->array = xpalloc (heap->array, &heap->capacity, 1, -1, |
|
|
sizeof heap->array[0]); |
|
|
|
|
|
heap->array[++heap->count] = item; |
|
|
heapify_up (heap->array, heap->count, heap->compare); |
|
|
|
|
|
return 0; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void * |
|
|
heap_remove_top (struct heap *heap) |
|
|
{ |
|
|
void *top; |
|
|
|
|
|
if (heap->count == 0) |
|
|
return nullptr; |
|
|
|
|
|
top = heap->array[1]; |
|
|
heap->array[1] = heap->array[heap->count--]; |
|
|
heapify_down (heap->array, heap->count, 1, heap->compare); |
|
|
|
|
|
return top; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void |
|
|
heapify_down (void **array, idx_t count, idx_t initial, |
|
|
int (*compare) (void const *, void const *)) |
|
|
{ |
|
|
void *element = array[initial]; |
|
|
|
|
|
idx_t parent = initial; |
|
|
while (parent <= count >> 1) |
|
|
{ |
|
|
idx_t child = 2 * parent; |
|
|
|
|
|
if (child < count && compare (array[child], array[child + 1]) < 0) |
|
|
child++; |
|
|
|
|
|
if (compare (array[child], element) <= 0) |
|
|
break; |
|
|
|
|
|
array[parent] = array[child]; |
|
|
parent = child; |
|
|
} |
|
|
|
|
|
array[parent] = element; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void |
|
|
heapify_up (void **array, idx_t count, |
|
|
int (*compare) (void const *, void const *)) |
|
|
{ |
|
|
idx_t k = count; |
|
|
void *new_element = array[k]; |
|
|
|
|
|
while (k != 1 && compare (array[k >> 1], new_element) <= 0) |
|
|
{ |
|
|
array[k] = array[k >> 1]; |
|
|
k >>= 1; |
|
|
} |
|
|
|
|
|
array[k] = new_element; |
|
|
} |
|
|
|