Generic array-based extraction-efficient heap implementation. More...
#include "qos_debug.h"#include <stdio.h>#include <unistd.h>#include <stdlib.h>Go to the source code of this file.
Defines | |
| #define | kal_define_eheap(key_type, value_type) |
| Define eheap related types: use this macro only once per compilation unit. | |
| #define | kal_eheap_key_lt(a, b) ((a) < (b)) |
| #define | kal_eheap_node_t(key_type, value_type) struct kal_eheap_node_##key_type ##_##value_type ##_t |
| Template-like type for a eheap node (users should not use this). | |
| #define | kal_eheap_t(key_type, value_type) kal_eheap_##key_type ##_##value_type ##_t |
| Template-like type for a eheap container. | |
| #define | kal_eheap_iterator_t(key_type, value_type) kal_eheap_iterator_##key_type ##_##value_type ##_t |
| Template-like type for a eheap iterator. | |
| #define | kal_eheap_init(self, N) |
| Initialize an empty eheap with (initial) max storage capacity of N. | |
| #define | kal_eheap_cleanup(self) |
| #define | kal_eheap_nodecpy(self, dst_pos, src_pos) |
| Move a node contents from src_pos to dst_pos, overwriting destination contents. | |
| #define | kal_eheap_push_down(self, param_pos, param_key) |
| Push the specified key down the heap, as if it started from position (1-based) param_pos, moving up all the necessary items. | |
| #define | kal_eheap_push_up(self, param_pos, param_key) |
| Push the specified key up the heap, as if it started from position (1-based) param_pos, moving down all the necessary items. | |
| #define | kal_eheap_add(self, _key, _value, _p_it) |
| Add the pair (_key, _value) to the eheap, and store the corresponding removal iterator in *_p_it. | |
| #define | kal_eheap_get_min(self, p_key, p_value) |
| Return (without removing) the heap root pair, corresponding to the minimum key value. | |
| #define | kal_eheap_del_min(self) |
| Remove the top (root) of the heap, alias the minimum-key element. | |
| #define | kal_eheap_del(self, p_it) |
| Remove an arbitrary element of the heap, through the iterator stored during a kal_eheap_add() operation. | |
| #define | kal_eheap_size(self) (self)->num_elems |
| Return the current size of the heap. | |
| #define | kal_eheap_iterator_valid(p_it) ((p_it)->pos != 0) |
| Check if provided iterator is valid or has been invalidated. | |
| #define | kal_eheap_iterator_init(p_it) |
| Initialize an iterator as non-valid. | |
| #define | kal_eheap_begin(self, p_it) |
| #define | kal_eheap_has_next(self, p_it) ((p_it)->pos < (self)->num_elems) |
| #define | kal_eheap_next(self, p_it, p_key, p_val) |
Generic array-based extraction-efficient heap implementation.
Definition in file kal_eheap.h.
| #define kal_define_eheap | ( | key_type, | |||
| value_type | ) |
typedef struct kal_eheap_iterator_##key_type ##_##value_type ##_t { \ int pos; \ } kal_eheap_iterator_##key_type ##_##value_type ##_t; \ typedef struct kal_eheap_node_##key_type ##_##value_type ##_t { \ key_type key; \ value_type value; \ kal_eheap_iterator_##key_type ##_##value_type ##_t *p_iterator; \ } kal_eheap_node_##key_type ##_##value_type ##_t; \ typedef struct kal_eheap_##key_type ##_##value_type ##_t { \ kal_eheap_node_t(key_type, value_type) *elems; \ int num_elems; \ int max_num_elems; \ } kal_eheap_##key_type ##_##value_type ##_t
Define eheap related types: use this macro only once per compilation unit.
Definition at line 14 of file kal_eheap.h.
| #define kal_eheap_add | ( | self, | |||
| _key, | |||||
| _value, | |||||
| _p_it | ) |
({ \
qos_rv __rv = QOS_OK; \
typeof((self)->elems[0].p_iterator) _a_p_it = (_p_it); \
do { \
int _a_pos = (self)->num_elems + 1; \
if (_a_pos == (self)->max_num_elems + 1) { \
__rv = QOS_E_FULL; \
break; \
} \
(self)->num_elems++; \
_a_pos = kal_eheap_push_up((self), _a_pos, (_key)); \
(self)->elems[_a_pos - 1].key = (_key); \
(self)->elems[_a_pos - 1].value = (_value); \
if (_a_p_it) { \
(self)->elems[_a_pos - 1].p_iterator = _a_p_it; \
_a_p_it->pos = _a_pos; \
} else { \
(self)->elems[_a_pos - 1].p_iterator = NULL; \
} \
} while (0); \
__rv; \
})
Add the pair (_key, _value) to the eheap, and store the corresponding removal iterator in *_p_it.
Definition at line 128 of file kal_eheap.h.
Referenced by kal_eheap_t(), and main().
| #define kal_eheap_begin | ( | self, | |||
| p_it | ) |
do { \ (p_it)->pos = 0; \ } while (0)
Definition at line 242 of file kal_eheap.h.
| #define kal_eheap_cleanup | ( | self | ) |
({ \
qos_rv __rv = QOS_OK; \
do { \
qos_free((self)->elems); \
(self)->num_elems = (self)->max_num_elems = 0; \
} while (0); \
__rv; \
})
Definition at line 64 of file kal_eheap.h.
Referenced by kal_eheap_t(), and main().
| #define kal_eheap_del | ( | self, | |||
| p_it | ) |
({ \
qos_rv __rv = QOS_OK; \
int _d_pos = (p_it)->pos, _d_pos2; \
typeof((self)->elems[0].key) _d_key; \
do { \
if ((self)->num_elems == 0) { \
__rv = QOS_E_EMPTY; \
break; \
} \
if (_d_pos == 0) { /* Invalid iterator detection */ \
__rv = QOS_E_INVALID_PARAM; \
break; \
} \
(p_it)->pos = 0; /* Invalidate iterator */ \
_d_key = (self)->elems[(self)->num_elems - 1].key; \
(self)->num_elems--; \
if ((self)->num_elems == 0 || (self)->num_elems + 1 == _d_pos) \
break; \
_d_pos2 = kal_eheap_push_down((self), _d_pos, _d_key); \
if (_d_pos2 == _d_pos) \
_d_pos2 = kal_eheap_push_up((self), _d_pos, _d_key); \
/* We use on purpose num_elems + 1, as we know it is legal */ \
kal_eheap_nodecpy((self), _d_pos2, (self)->num_elems + 1); \
} while (0); \
__rv; \
})
Remove an arbitrary element of the heap, through the iterator stored during a kal_eheap_add() operation.
Definition at line 198 of file kal_eheap.h.
Referenced by kal_eheap_t().
| #define kal_eheap_del_min | ( | self | ) |
({ \
qos_rv __dm_rv = QOS_OK; \
int _dm_pos = 1; \
int _dm_key; \
do { \
if ((self)->num_elems == 0) { \
__dm_rv = QOS_E_EMPTY; \
break; \
} \
if ((self)->elems[0].p_iterator) \
(self)->elems[0].p_iterator->pos = 0; /* Invalidate iterator */ \
_dm_key = (self)->elems[(self)->num_elems - 1].key; \
(self)->num_elems--; \
/* printf("Pushing down pos: %d\n", _dm_pos); \
*/ _dm_pos = kal_eheap_push_down((self), _dm_pos, _dm_key); \
/* printf("Copying into pos: %d\n", _dm_pos); \
*/ /* This copies on purpose from a position == num_elems + 1, 'cause we know it is legal */ \
kal_eheap_nodecpy((self), _dm_pos, (self)->num_elems + 1); \
} while (0); \
__dm_rv; \
})
Remove the top (root) of the heap, alias the minimum-key element.
Definition at line 171 of file kal_eheap.h.
Referenced by kal_eheap_t(), and main().
| #define kal_eheap_get_min | ( | self, | |||
| p_key, | |||||
| p_value | ) |
({ \
qos_rv __gm_rv = QOS_OK; \
do { \
if ((self)->num_elems == 0) { \
__gm_rv = QOS_E_EMPTY; \
break; \
} \
*(p_key) = (self)->elems[0].key; \
*(p_value) = (self)->elems[0].value; \
} while (0); \
__gm_rv; \
})
Return (without removing) the heap root pair, corresponding to the minimum key value.
Definition at line 152 of file kal_eheap.h.
Referenced by kal_eheap_t(), and main().
| #define kal_eheap_has_next | ( | self, | |||
| p_it | ) | ((p_it)->pos < (self)->num_elems) |
Definition at line 247 of file kal_eheap.h.
| #define kal_eheap_init | ( | self, | |||
| N | ) |
({ \
qos_rv __rv = QOS_OK; \
do { \
(self)->elems = qos_malloc(sizeof((self)->elems[0]) << N); \
if ((self)->elems == NULL) { \
__rv = QOS_E_NO_MEMORY; \
break; \
} \
(self)->max_num_elems = 1 << N; \
(self)->num_elems = 0; \
} while (0); \
__rv; \
})
Initialize an empty eheap with (initial) max storage capacity of N.
Definition at line 50 of file kal_eheap.h.
Referenced by kal_eheap_t(), and main().
| #define kal_eheap_iterator_init | ( | p_it | ) |
do { \ (p_it)->pos = 0; \ } while (0)
Initialize an iterator as non-valid.
Definition at line 237 of file kal_eheap.h.
| #define kal_eheap_iterator_t | ( | key_type, | |||
| value_type | ) | kal_eheap_iterator_##key_type ##_##value_type ##_t |
Template-like type for a eheap iterator.
Definition at line 42 of file kal_eheap.h.
Referenced by kal_eheap_t().
| #define kal_eheap_iterator_valid | ( | p_it | ) | ((p_it)->pos != 0) |
Check if provided iterator is valid or has been invalidated.
Definition at line 234 of file kal_eheap.h.
Referenced by kal_eheap_t().
| #define kal_eheap_key_lt | ( | a, | |||
| b | ) | ((a) < (b)) |
Definition at line 30 of file kal_eheap.h.
| #define kal_eheap_next | ( | self, | |||
| p_it, | |||||
| p_key, | |||||
| p_val | ) |
({ \
typeof(&(self)->elems[0].key) _p_key = (p_key); \
typeof(&(self)->elems[0].value) _p_val = (p_val); \
qos_rv __rv = QOS_OK; \
do { \
if ((p_it)->pos < (self)->num_elems) { \
(p_it)->pos++; \
if (_p_key) \
*(_p_key) = (self)->elems[(p_it)->pos - 1].key; \
if (_p_val) \
*(_p_val) = (self)->elems[(p_it)->pos - 1].value; \
} else { \
__rv = QOS_E_EMPTY; \
break; \
} \
} while (0); \
__rv; \
})
Definition at line 250 of file kal_eheap.h.
| #define kal_eheap_node_t | ( | key_type, | |||
| value_type | ) | struct kal_eheap_node_##key_type ##_##value_type ##_t |
Template-like type for a eheap node (users should not use this).
Definition at line 34 of file kal_eheap.h.
| #define kal_eheap_nodecpy | ( | self, | |||
| dst_pos, | |||||
| src_pos | ) |
do { \ (self)->elems[(dst_pos) - 1] = (self)->elems[(src_pos) - 1]; \ if ((self)->elems[(dst_pos) - 1].p_iterator) \ (self)->elems[(dst_pos) - 1].p_iterator->pos = (dst_pos); \ } while (0)
Move a node contents from src_pos to dst_pos, overwriting destination contents.
Definition at line 74 of file kal_eheap.h.
| #define kal_eheap_push_down | ( | self, | |||
| param_pos, | |||||
| param_key | ) |
({ \
int _pd_pos = (param_pos); \
do { \
int _pd_pos_child; \
typeof((self)->elems[0].key) _pd_key = (param_key); \
/* printf("pos: %d\n", _pd_pos); fflush(stdout); \
*/ _pd_pos_child = _pd_pos * 2; \
while ( \
((_pd_pos_child <= (self)->num_elems) && kal_eheap_key_lt((self)->elems[_pd_pos_child - 1].key, _pd_key)) \
|| ((_pd_pos_child + 1 <= (self)->num_elems) && kal_eheap_key_lt((self)->elems[_pd_pos_child].key, _pd_key)) \
) { \
if ((_pd_pos_child + 1 <= (self)->num_elems) && kal_eheap_key_lt((self)->elems[_pd_pos_child].key, (self)->elems[_pd_pos_child - 1].key)) \
_pd_pos_child++; \
kal_eheap_nodecpy((self), _pd_pos, _pd_pos_child); \
_pd_pos = _pd_pos_child; \
_pd_pos_child = _pd_pos * 2; \
/* printf("pos: %d\n", _pd_pos); \
*/ } \
} while (0); \
_pd_pos; \
})
Push the specified key down the heap, as if it started from position (1-based) param_pos, moving up all the necessary items.
Returns the correct position, in which the element has not been copied yet.
Definition at line 86 of file kal_eheap.h.
| #define kal_eheap_push_up | ( | self, | |||
| param_pos, | |||||
| param_key | ) |
({ \
int _pu_pos = (param_pos); \
do { \
int _pu_pos_fath = _pu_pos / 2; \
/* printf("xpos: %d\n", _pu_pos); fflush(stdout); \
*/ while ((_pu_pos != 1) && kal_eheap_key_lt((param_key), (self)->elems[_pu_pos_fath - 1].key)) { \
kal_eheap_nodecpy((self), _pu_pos, _pu_pos_fath); \
_pu_pos = _pu_pos_fath; \
_pu_pos_fath = _pu_pos / 2; \
/* printf("pos: %d\n", _pu_pos); fflush(stdout); \
*/ } \
} while (0); \
_pu_pos; \
})
Push the specified key up the heap, as if it started from position (1-based) param_pos, moving down all the necessary items.
Returns the correct position, in which the element has not been copied yet.
Definition at line 111 of file kal_eheap.h.
| #define kal_eheap_size | ( | self | ) | (self)->num_elems |
Return the current size of the heap.
Definition at line 226 of file kal_eheap.h.
Referenced by kal_eheap_t(), and main().
| #define kal_eheap_t | ( | key_type, | |||
| value_type | ) | kal_eheap_##key_type ##_##value_type ##_t |
Template-like type for a eheap container.
Definition at line 38 of file kal_eheap.h.
1.6.3