LibJuno 0.42.0
LibJuno is a lightweight C99 library designed specifically for embedded systems.
Loading...
Searching...
No Matches
heap_api.h
Go to the documentation of this file.
1/*
2 MIT License
3
4 Copyright (c) 2025 Robin A. Onsay
5
6 Permission is hereby granted, free of charge, to any person obtaining
7 a copy of this software and associated documentation files
8 (the "Software"), to deal in the Software without restriction,
9 including without limitation the rights to use, copy, modify, merge,
10 publish, distribute, sublicense, and/or sell copies of the Software,
11 and to permit persons to whom the Software is furnished to do so,
12 subject to the following conditions:
13
14 The above copyright notice and this permission notice shall be
15 included in all copies or substantial portions of the Software.
16*/
17
27#ifndef JUNO_DS_API_H
28#define JUNO_DS_API_H
29#include "juno/macros.h"
30#include "juno/status.h"
31#include "juno/module.h"
32#include <stdbool.h>
33#include <stddef.h>
34#ifdef __cplusplus
35extern "C"
36{
37#endif
38
114typedef struct JUNO_DS_HEAP_ROOT_TAG JUNO_DS_HEAP_ROOT_T;
121JUNO_MODULE_RESULT(JUNO_DS_HEAP_INDEX_RESULT_T, size_t);
122
126JUNO_MODULE_OPTION(JUNO_DS_HEAP_INDEX_OPTION_T, size_t);
127
131JUNO_MODULE_RESULT(JUNO_DS_HEAP_INDEX_OPTION_RESULT_T, JUNO_DS_HEAP_INDEX_OPTION_T);
132
137JUNO_MODULE_RESULT(JUNO_DS_HEAP_COMPARE_RESULT_T, bool);
138
151struct JUNO_DS_HEAP_ROOT_TAG JUNO_MODULE_ROOT(JUNO_DS_HEAP_API_T,
152 size_t zCapacity;
153 size_t zLength;
154);
155
167{
169 JUNO_DS_HEAP_COMPARE_RESULT_T (*Compare)(JUNO_DS_HEAP_ROOT_T *ptHeap, size_t parent, size_t child);
170 JUNO_STATUS_T (*Swap)(JUNO_DS_HEAP_ROOT_T *ptHeap, size_t iFrom, size_t iTo);
171 JUNO_STATUS_T (*Reset)(JUNO_DS_HEAP_ROOT_T *ptHeap, size_t iIndex);
172};
173
187
201
208{
210 if(!(ptHeap && ptHeap->ptApi && ptHeap->zCapacity))
211 {
213 }
214 return tStatus;
215}
216
228static inline JUNO_STATUS_T JunoDs_Heap_Init(JUNO_DS_HEAP_ROOT_T *ptHeap, const JUNO_DS_HEAP_API_T *ptApi, size_t zCapacity)
229{
230 JUNO_ASSERT_EXISTS(ptHeap);
231 ptHeap->ptApi = ptApi;
232 ptHeap->zCapacity = zCapacity;
233 ptHeap->zLength = 0;
234 return JunoDs_Heap_Verify(ptHeap);
235}
236
245static inline JUNO_DS_HEAP_INDEX_OPTION_RESULT_T JunoDs_Heap_ChildGetLeft(JUNO_DS_HEAP_ROOT_T *ptHeap, size_t iIndex)
246{
247 JUNO_DS_HEAP_INDEX_OPTION_RESULT_T tResult = {JUNO_STATUS_SUCCESS, {false, 0}};
248 tResult.tStatus = JunoDs_Heap_Verify(ptHeap);
249 JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult);
250 iIndex = 2 * iIndex + 1;
251 if(iIndex > ptHeap->zCapacity || ptHeap->zLength > ptHeap->zCapacity)
252 {
253 tResult.tStatus = JUNO_STATUS_ERR;
254 return tResult;
255 }
256 if(iIndex >= ptHeap->zLength)
257 {
258 tResult.tStatus = JUNO_STATUS_SUCCESS;
259 tResult.tOk.bIsSome = false;
260 return tResult;
261 }
262 tResult.tStatus = JUNO_STATUS_SUCCESS;
263 tResult.tOk.bIsSome = true;
264 tResult.tOk.tSome = iIndex;
265 return tResult;
266}
267
272static inline JUNO_DS_HEAP_INDEX_OPTION_RESULT_T JunoDs_Heap_ChildGetRight(JUNO_DS_HEAP_ROOT_T *ptHeap, size_t iIndex)
273{
274 JUNO_DS_HEAP_INDEX_OPTION_RESULT_T tResult = {JUNO_STATUS_SUCCESS, {false, 0}};
275 tResult.tStatus = JunoDs_Heap_Verify(ptHeap);
276 JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult);
277 iIndex = 2 * iIndex + 2;
278 if(iIndex > ptHeap->zCapacity || ptHeap->zLength > ptHeap->zCapacity)
279 {
280 tResult.tStatus = JUNO_STATUS_ERR;
281 return tResult;
282 }
283 if(iIndex >= ptHeap->zLength)
284 {
285 tResult.tStatus = JUNO_STATUS_SUCCESS;
286 tResult.tOk.bIsSome = false;
287 return tResult;
288 }
289 tResult.tStatus = JUNO_STATUS_SUCCESS;
290 tResult.tOk.bIsSome = true;
291 tResult.tOk.tSome = iIndex;
292 return tResult;
293}
294
299static inline JUNO_DS_HEAP_INDEX_OPTION_RESULT_T JunoDs_Heap_ChildGetParent(JUNO_DS_HEAP_ROOT_T *ptHeap, size_t iIndex)
300{
301 JUNO_DS_HEAP_INDEX_OPTION_RESULT_T tResult = {JUNO_STATUS_SUCCESS, {false, 0}};
302 tResult.tStatus = JunoDs_Heap_Verify(ptHeap);
303 JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult);
304 iIndex = (iIndex - 1)/2;
305 if(iIndex > ptHeap->zCapacity || ptHeap->zLength > ptHeap->zCapacity)
306 {
307 tResult.tStatus = JUNO_STATUS_ERR;
308 return tResult;
309 }
310 if(iIndex >= ptHeap->zLength)
311 {
312 tResult.tStatus = JUNO_STATUS_SUCCESS;
313 tResult.tOk.bIsSome = false;
314 return tResult;
315 }
316 tResult.tStatus = JUNO_STATUS_SUCCESS;
317 tResult.tOk.bIsSome = true;
318 tResult.tOk.tSome = iIndex;
319 return tResult;
320}
321
332static inline JUNO_DS_HEAP_INDEX_RESULT_T JunoDs_Heap_Insert(JUNO_DS_HEAP_ROOT_T *ptHeap)
333{
334 JUNO_DS_HEAP_INDEX_RESULT_T tResult = {JUNO_STATUS_SUCCESS, 0};
335 tResult.tStatus = JunoDs_Heap_Verify(ptHeap);
336 JUNO_ASSERT_SUCCESS(tResult.tStatus, return tResult);
337 if(ptHeap->zLength >= ptHeap->zCapacity)
338 {
339 tResult.tStatus = JUNO_STATUS_ERR;
340 return tResult;
341 }
342 tResult.tOk = ptHeap->zLength;
343 ptHeap->zLength += 1;
344 return tResult;
345}
346
356{
358 tStatus = JunoDs_Heap_Verify(ptHeap);
359 JUNO_ASSERT_SUCCESS(tStatus, return tStatus);
360 if(ptHeap->zLength <= 0)
361 {
362 tStatus = JUNO_STATUS_ERR;
363 return tStatus;
364 }
365 JUNO_DS_HEAP_INDEX_OPTION_RESULT_T iIndexResult = JunoDs_Heap_ChildGetParent(ptHeap, ptHeap->zLength);
366 JUNO_ASSERT_SUCCESS(iIndexResult.tStatus, return iIndexResult.tStatus);
367 if(!iIndexResult.tOk.bIsSome)
368 {
369 return tStatus;
370 }
371 size_t iIndex = iIndexResult.tOk.tSome;
372 for(size_t i = 0; i <= iIndex; ++i)
373 {
374 size_t iCurrentIndex = iIndex - i;
375 tStatus = JunoDs_Heap_SiftDown(ptHeap, iCurrentIndex);
376 JUNO_ASSERT_SUCCESS(tStatus, continue);
377 }
378 return tStatus;
379}
380
393{
395 tStatus = JunoDs_Heap_Verify(ptHeap);
396 JUNO_ASSERT_SUCCESS(tStatus, return tStatus);
397 if(ptHeap->zLength <= 0)
398 {
399 tStatus = JUNO_STATUS_ERR;
400 return tStatus;
401 }
402 tStatus = ptHeap->ptApi->Swap(ptHeap, ptHeap->zLength-1, 0);
403 JUNO_ASSERT_SUCCESS(tStatus, return tStatus);
404 ptHeap->ptApi->Reset(ptHeap, ptHeap->zLength-1);
405 JUNO_ASSERT_SUCCESS(tStatus, return tStatus);
406 ptHeap->zLength -= 1;
407 return JunoDs_Heap_SiftDown(ptHeap, 0);
408}
409
410#ifdef __cplusplus
411}
412#endif
413#endif // JUNO_DS_API_H
JUNO_STATUS_T JunoDs_Heap_SiftDown(JUNO_DS_HEAP_ROOT_T *ptHeap, size_t iStart)
Sift down from a starting index to restore the heap property.
Definition juno_heap.c:51
static JUNO_DS_HEAP_INDEX_RESULT_T JunoDs_Heap_Insert(JUNO_DS_HEAP_ROOT_T *ptHeap)
Reserve a new slot at the end of the heap array and return its index.
Definition heap_api.h:332
static JUNO_STATUS_T JunoDs_Heap_Verify(JUNO_DS_HEAP_ROOT_T *ptHeap)
Verify that the heap root has been initialized properly.
Definition heap_api.h:207
static JUNO_DS_HEAP_INDEX_OPTION_RESULT_T JunoDs_Heap_ChildGetLeft(JUNO_DS_HEAP_ROOT_T *ptHeap, size_t iIndex)
Compute the left child index of iIndex.
Definition heap_api.h:245
static JUNO_STATUS_T JunoDs_Heap_Heapify(JUNO_DS_HEAP_ROOT_T *ptHeap)
Build a heap in-place from the current array contents.
Definition heap_api.h:355
static JUNO_DS_HEAP_INDEX_OPTION_RESULT_T JunoDs_Heap_ChildGetRight(JUNO_DS_HEAP_ROOT_T *ptHeap, size_t iIndex)
Compute the right child index of iIndex.
Definition heap_api.h:272
struct JUNO_DS_HEAP_ROOT_TAG JUNO_DS_HEAP_ROOT_T
Definition heap_api.h:114
JUNO_STATUS_T JunoDs_Heap_Update(JUNO_DS_HEAP_ROOT_T *ptHeap)
Bubble-up the last inserted element to restore the heap property.
Definition juno_heap.c:5
static JUNO_DS_HEAP_INDEX_OPTION_RESULT_T JunoDs_Heap_ChildGetParent(JUNO_DS_HEAP_ROOT_T *ptHeap, size_t iIndex)
Compute the parent index of iIndex.
Definition heap_api.h:299
static JUNO_STATUS_T JunoDs_Heap_Delete(JUNO_DS_HEAP_ROOT_T *ptHeap)
Remove the root element and restore the heap property.
Definition heap_api.h:392
static JUNO_STATUS_T JunoDs_Heap_Init(JUNO_DS_HEAP_ROOT_T *ptHeap, const JUNO_DS_HEAP_API_T *ptApi, size_t zCapacity)
Initialize a heap root with the given API and capacity.
Definition heap_api.h:228
#define JUNO_ASSERT_EXISTS(ptr)
Definition macros.h:28
#define JUNO_ASSERT_SUCCESS(tStatus, failOp)
Definition macros.h:52
#define JUNO_MODULE_RESULT(NAME_T, OK_T)
Defines a result type combining a status and a success payload.
Definition module.h:223
#define JUNO_MODULE_ROOT(API_T,...)
Definition module.h:182
#define JUNO_MODULE_OPTION(NAME_T, SOME_T)
Defines an option type combining a flag to indicate some and a success payload.
Definition module.h:242
#define JUNO_STATUS_ERR
Definition status.h:25
int32_t JUNO_STATUS_T
Definition status.h:23
#define JUNO_STATUS_NULLPTR_ERROR
Definition status.h:26
#define JUNO_STATUS_SUCCESS
Definition status.h:24
API vtable you must implement to adapt the heap to your storage.
Definition heap_api.h:167
JUNO_STATUS_T(* Swap)(JUNO_DS_HEAP_ROOT_T *ptHeap, size_t iFrom, size_t iTo)
Definition heap_api.h:170
JUNO_STATUS_T(* Reset)(JUNO_DS_HEAP_ROOT_T *ptHeap, size_t iIndex)
Definition heap_api.h:171
JUNO_DS_HEAP_COMPARE_RESULT_T(* Compare)(JUNO_DS_HEAP_ROOT_T *ptHeap, size_t parent, size_t child)
Compare two values to perform the heap operation.
Definition heap_api.h:169