| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| |
| |
|
|
| #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; |
| } |
|
|