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