/* * Copyright (c) 2025 Aerlync Labs Inc. * * SPDX-License-Identifier: Apache-2.0 */ #include #include #include LOG_MODULE_REGISTER(min_heap); /** * @brief Restore heap order by moving a node up the tree. * * Moves the node at the given index upward in the heap until the min-heap * property is restored. * * @param heap Pointer to the min-heap. * @param index Index of the node to heapify upwards. */ static void heapify_up(struct min_heap *heap, size_t index) { while (index > 0) { size_t parent = (index - 1) / 2; void *curr = min_heap_get_element(heap, index); void *par = min_heap_get_element(heap, parent); if (heap->cmp(curr, par) >= 0) { break; } byteswp(curr, par, heap->elem_size); index = parent; } } /** * @brief Restore heap order by moving a node down the tree. * * Moves the node at the specified index downward in the heap until the * min-heap property is restored. * * @param heap Pointer to the min-heap. * @param index Index of the node to heapify downward. */ static void heapify_down(struct min_heap *heap, size_t index) { /* Terminate the loop naturally when the left child is out of bounds */ for (size_t left = 2 * index + 1; left < heap->size; left = 2 * index + 1) { size_t right = left + 1; size_t smallest = index; void *elem_index = min_heap_get_element(heap, index); void *elem_left = min_heap_get_element(heap, left); void *elem_smallest = elem_index; if (heap->cmp(elem_left, elem_index) < 0) { smallest = left; elem_smallest = elem_left; } if (right < heap->size) { void *elem_right = min_heap_get_element(heap, right); if (heap->cmp(elem_right, elem_smallest) < 0) { smallest = right; elem_smallest = elem_right; } } if (smallest == index) { break; } byteswp(elem_index, elem_smallest, heap->elem_size); index = smallest; } } void min_heap_init(struct min_heap *heap, void *storage, size_t cap, size_t elem_size, min_heap_cmp_t cmp) { heap->storage = storage; heap->capacity = cap; heap->elem_size = elem_size; heap->cmp = cmp; heap->size = 0; } void *min_heap_peek(const struct min_heap *heap) { if (heap->size == 0) { return NULL; } return min_heap_get_element(heap, 0); } int min_heap_push(struct min_heap *heap, const void *item) { if (heap->size >= heap->capacity) { return -ENOMEM; } void *dest = min_heap_get_element(heap, heap->size); memcpy(dest, item, heap->elem_size); heapify_up(heap, heap->size); heap->size++; return 0; } bool min_heap_remove(struct min_heap *heap, size_t id, void *out_buf) { if (id >= heap->size) { return false; } void *removed = min_heap_get_element(heap, id); memcpy(out_buf, removed, heap->elem_size); heap->size--; if (id != heap->size) { void *last = min_heap_get_element(heap, heap->size); memcpy(removed, last, heap->elem_size); heapify_down(heap, id); heapify_up(heap, id); } return true; } bool min_heap_pop(struct min_heap *heap, void *out_buf) { return min_heap_remove(heap, 0, out_buf); } void *min_heap_find(struct min_heap *heap, min_heap_eq_t eq, const void *other, size_t *out_id) { void *element; for (size_t i = 0; i < heap->size; ++i) { element = min_heap_get_element(heap, i); if (eq(element, other)) { if (out_id) { *out_id = i; } return element; } } return NULL; }