Primary Git Repository for the Zephyr Project. Zephyr is a new generation, scalable, optimized, secure RTOS for multiple hardware architectures.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

178 lines
3.6 KiB

/*
* Copyright (c) 2025 Aerlync Labs Inc.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdlib.h>
#include <zephyr/sys/min_heap.h>
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(min_heap);
/**
* @brief Swap two elements in the heap.
*
* This function swaps the contents of two elements at the specified indices
* within the heap.
*
* @param heap Pointer to the min-heap.
* @param a Index of the first element.
* @param b Index of the second element.
*/
static void swap(struct min_heap *heap, size_t a, size_t b)
{
uint8_t tmp[heap->elem_size];
void *elem_a = min_heap_get_element(heap, a);
void *elem_b = min_heap_get_element(heap, b);
memcpy(tmp, elem_a, heap->elem_size);
memcpy(elem_a, elem_b, heap->elem_size);
memcpy(elem_b, tmp, heap->elem_size);
}
/**
* @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)
{
size_t parent;
void *curr, *par;
while (index > 0) {
parent = (index - 1) / 2;
curr = min_heap_get_element(heap, index);
par = min_heap_get_element(heap, parent);
if (heap->cmp(curr, par) >= 0) {
break;
}
swap(heap, index, parent);
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)
{
size_t left, right, smallest;
while (true) {
left = 2 * index + 1;
right = 2 * index + 2;
smallest = index;
if (left < heap->size &&
heap->cmp(min_heap_get_element(heap, left),
min_heap_get_element(heap, smallest)) < 0) {
smallest = left;
}
if (right < heap->size &&
heap->cmp(min_heap_get_element(heap, right),
min_heap_get_element(heap, smallest)) < 0) {
smallest = right;
}
if (smallest == index) {
break;
}
swap(heap, index, smallest);
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;
}