Adding functions table to heap and intervalheap
This commit is contained in:
1 parent
fa49fddd8f
commit
64c3a99922
4 files changed
+345
-261
No files matched your search
+84
-51
@@ -112,7 +112,7 @@ static const char *cmc_string_fmt_heap = "struct %s<%s> "
|
||||
"capacity:%" PRIuMAX ", "
|
||||
"count:%" PRIuMAX ", "
|
||||
"type:%s, "
|
||||
"cmp:%p, "
|
||||
"f_val:%p, "
|
||||
"alloc:%p, "
|
||||
"callbacks: %p}";
|
||||
|
||||
@@ -161,20 +161,45 @@ struct cmc_callbacks_heap
|
||||
/* Heap order (MaxHeap or MinHeap) */ \
|
||||
enum cmc_heap_order HO; \
|
||||
\
|
||||
/* Element comparison function */ \
|
||||
int (*cmp)(V, V); \
|
||||
/* Flags indicating errors or success */ \
|
||||
int flag; \
|
||||
\
|
||||
/* Function that returns an iterator to the start of the heap */ \
|
||||
struct SNAME##_iter (*it_start)(struct SNAME *); \
|
||||
\
|
||||
/* Function that returns an iterator to the end of the heap */ \
|
||||
struct SNAME##_iter (*it_end)(struct SNAME *); \
|
||||
/* Value function table */ \
|
||||
struct SNAME##_ftab_val *f_val; \
|
||||
\
|
||||
/* Custom allocation functions */ \
|
||||
struct cmc_alloc_node *alloc; \
|
||||
\
|
||||
/* Custom callback functions */ \
|
||||
struct cmc_callbacks_heap *callbacks; \
|
||||
\
|
||||
/* Function that returns an iterator to the start of the heap */ \
|
||||
struct SNAME##_iter (*it_start)(struct SNAME *); \
|
||||
\
|
||||
/* Function that returns an iterator to the end of the heap */ \
|
||||
struct SNAME##_iter (*it_end)(struct SNAME *); \
|
||||
}; \
|
||||
\
|
||||
/* Value struct function table */ \
|
||||
struct SNAME##_ftab_val \
|
||||
{ \
|
||||
/* Comparator function */ \
|
||||
int (*cmp)(V, V); \
|
||||
\
|
||||
/* Copy function */ \
|
||||
V (*cpy)(V); \
|
||||
\
|
||||
/* To string function */ \
|
||||
bool (*str)(FILE *, V); \
|
||||
\
|
||||
/* Free from memory function */ \
|
||||
void (*free)(V); \
|
||||
\
|
||||
/* Hash function */ \
|
||||
size_t (*hash)(V); \
|
||||
\
|
||||
/* Priority function */ \
|
||||
int (*pri)(V, V); \
|
||||
}; \
|
||||
\
|
||||
/* Heap Iterator */ \
|
||||
@@ -196,12 +221,13 @@ struct cmc_callbacks_heap
|
||||
/* Collection Functions */ \
|
||||
/* Collection Allocation and Deallocation */ \
|
||||
struct SNAME *PFX##_new(size_t capacity, enum cmc_heap_order HO, \
|
||||
int (*compare)(V, V)); \
|
||||
struct SNAME *PFX##_new_custom( \
|
||||
size_t capacity, enum cmc_heap_order HO, int (*compare)(V, V), \
|
||||
struct cmc_alloc_node *alloc, struct cmc_callbacks_heap *callbacks); \
|
||||
void PFX##_clear(struct SNAME *_heap_, void (*deallocator)(V)); \
|
||||
void PFX##_free(struct SNAME *_heap_, void (*deallocator)(V)); \
|
||||
struct SNAME##_ftab_val *f_val); \
|
||||
struct SNAME *PFX##_new_custom(size_t capacity, enum cmc_heap_order HO, \
|
||||
struct SNAME##_ftab_val *f_val, \
|
||||
struct cmc_alloc_node *alloc, \
|
||||
struct cmc_callbacks_heap *callbacks); \
|
||||
void PFX##_clear(struct SNAME *_heap_); \
|
||||
void PFX##_free(struct SNAME *_heap_); \
|
||||
/* Customization of Allocation and Callbacks */ \
|
||||
void PFX##_customize(struct SNAME *_heap_, struct cmc_alloc_node *alloc, \
|
||||
struct cmc_callbacks_heap *callbacks); \
|
||||
@@ -218,7 +244,7 @@ struct cmc_callbacks_heap
|
||||
size_t PFX##_capacity(struct SNAME *_heap_); \
|
||||
/* Collection Utility */ \
|
||||
bool PFX##_resize(struct SNAME *_heap_, size_t capacity); \
|
||||
struct SNAME *PFX##_copy_of(struct SNAME *_heap_, V (*copy_func)(V)); \
|
||||
struct SNAME *PFX##_copy_of(struct SNAME *_heap_); \
|
||||
bool PFX##_equals(struct SNAME *_heap1_, struct SNAME *_heap2_); \
|
||||
struct cmc_string PFX##_to_string(struct SNAME *_heap_); \
|
||||
\
|
||||
@@ -255,7 +281,7 @@ struct cmc_callbacks_heap
|
||||
static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_heap_); \
|
||||
\
|
||||
struct SNAME *PFX##_new(size_t capacity, enum cmc_heap_order HO, \
|
||||
int (*compare)(V, V)) \
|
||||
struct SNAME##_ftab_val *f_val) \
|
||||
{ \
|
||||
struct cmc_alloc_node *alloc = &cmc_alloc_node_default; \
|
||||
\
|
||||
@@ -265,6 +291,9 @@ struct cmc_callbacks_heap
|
||||
if (HO != cmc_min_heap && HO != cmc_max_heap) \
|
||||
return NULL; \
|
||||
\
|
||||
if (!f_val) \
|
||||
return NULL; \
|
||||
\
|
||||
struct SNAME *_heap_ = alloc->malloc(sizeof(struct SNAME)); \
|
||||
\
|
||||
if (!_heap_) \
|
||||
@@ -281,20 +310,20 @@ struct cmc_callbacks_heap
|
||||
_heap_->capacity = capacity; \
|
||||
_heap_->count = 0; \
|
||||
_heap_->HO = HO; \
|
||||
_heap_->cmp = compare; \
|
||||
\
|
||||
_heap_->it_start = PFX##_impl_it_start; \
|
||||
_heap_->it_end = PFX##_impl_it_end; \
|
||||
\
|
||||
_heap_->flag = cmc_flags.OK; \
|
||||
_heap_->f_val = f_val; \
|
||||
_heap_->alloc = alloc; \
|
||||
_heap_->callbacks = NULL; \
|
||||
_heap_->it_start = PFX##_impl_it_start; \
|
||||
_heap_->it_end = PFX##_impl_it_end; \
|
||||
\
|
||||
return _heap_; \
|
||||
} \
|
||||
\
|
||||
struct SNAME *PFX##_new_custom( \
|
||||
size_t capacity, enum cmc_heap_order HO, int (*compare)(V, V), \
|
||||
struct cmc_alloc_node *alloc, struct cmc_callbacks_heap *callbacks) \
|
||||
struct SNAME *PFX##_new_custom(size_t capacity, enum cmc_heap_order HO, \
|
||||
struct SNAME##_ftab_val *f_val, \
|
||||
struct cmc_alloc_node *alloc, \
|
||||
struct cmc_callbacks_heap *callbacks) \
|
||||
{ \
|
||||
if (capacity < 1) \
|
||||
return NULL; \
|
||||
@@ -302,6 +331,9 @@ struct cmc_callbacks_heap
|
||||
if (HO != cmc_min_heap && HO != cmc_max_heap) \
|
||||
return NULL; \
|
||||
\
|
||||
if (!f_val) \
|
||||
return NULL; \
|
||||
\
|
||||
if (!alloc) \
|
||||
alloc = &cmc_alloc_node_default; \
|
||||
\
|
||||
@@ -321,24 +353,23 @@ struct cmc_callbacks_heap
|
||||
_heap_->capacity = capacity; \
|
||||
_heap_->count = 0; \
|
||||
_heap_->HO = HO; \
|
||||
_heap_->cmp = compare; \
|
||||
\
|
||||
_heap_->it_start = PFX##_impl_it_start; \
|
||||
_heap_->it_end = PFX##_impl_it_end; \
|
||||
\
|
||||
_heap_->flag = cmc_flags.OK; \
|
||||
_heap_->f_val = f_val; \
|
||||
_heap_->alloc = alloc; \
|
||||
_heap_->callbacks = callbacks; \
|
||||
_heap_->it_start = PFX##_impl_it_start; \
|
||||
_heap_->it_end = PFX##_impl_it_end; \
|
||||
\
|
||||
return _heap_; \
|
||||
} \
|
||||
\
|
||||
void PFX##_clear(struct SNAME *_heap_, void (*deallocator)(V)) \
|
||||
void PFX##_clear(struct SNAME *_heap_) \
|
||||
{ \
|
||||
if (deallocator) \
|
||||
if (_heap_->f_val->free) \
|
||||
{ \
|
||||
for (size_t i = 0; i < _heap_->count; i++) \
|
||||
{ \
|
||||
deallocator(_heap_->buffer[i]); \
|
||||
_heap_->f_val->free(_heap_->buffer[i]); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
@@ -347,13 +378,13 @@ struct cmc_callbacks_heap
|
||||
_heap_->count = 0; \
|
||||
} \
|
||||
\
|
||||
void PFX##_free(struct SNAME *_heap_, void (*deallocator)(V)) \
|
||||
void PFX##_free(struct SNAME *_heap_) \
|
||||
{ \
|
||||
if (deallocator) \
|
||||
if (_heap_->f_val->free) \
|
||||
{ \
|
||||
for (size_t i = 0; i < _heap_->count; i++) \
|
||||
{ \
|
||||
deallocator(_heap_->buffer[i]); \
|
||||
_heap_->f_val->free(_heap_->buffer[i]); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
@@ -422,7 +453,7 @@ struct cmc_callbacks_heap
|
||||
{ \
|
||||
for (size_t i = 0; i < _heap_->count; i++) \
|
||||
{ \
|
||||
if (_heap_->cmp(_heap_->buffer[i], element) == 0) \
|
||||
if (_heap_->f_val->cmp(_heap_->buffer[i], element) == 0) \
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
@@ -463,25 +494,27 @@ struct cmc_callbacks_heap
|
||||
if (!new_buffer) \
|
||||
return false; \
|
||||
\
|
||||
/* TODO zero out new slots */ \
|
||||
\
|
||||
_heap_->buffer = new_buffer; \
|
||||
_heap_->capacity = capacity; \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
struct SNAME *PFX##_copy_of(struct SNAME *_heap_, V (*copy_func)(V)) \
|
||||
struct SNAME *PFX##_copy_of(struct SNAME *_heap_) \
|
||||
{ \
|
||||
struct SNAME *result = \
|
||||
PFX##_new_custom(_heap_->capacity, _heap_->HO, _heap_->cmp, \
|
||||
PFX##_new_custom(_heap_->capacity, _heap_->HO, _heap_->f_val, \
|
||||
_heap_->alloc, _heap_->callbacks); \
|
||||
\
|
||||
if (!result) \
|
||||
return NULL; \
|
||||
\
|
||||
if (copy_func) \
|
||||
if (_heap_->f_val->cpy) \
|
||||
{ \
|
||||
for (size_t i = 0; i < _heap_->count; i++) \
|
||||
result->buffer[i] = copy_func(_heap_->buffer[i]); \
|
||||
result->buffer[i] = _heap_->f_val->cpy(_heap_->buffer[i]); \
|
||||
} \
|
||||
else \
|
||||
memcpy(result->buffer, _heap_->buffer, sizeof(V) * _heap_->count); \
|
||||
@@ -498,7 +531,8 @@ struct cmc_callbacks_heap
|
||||
\
|
||||
for (size_t i = 0; i < PFX##_count(_heap1_); i++) \
|
||||
{ \
|
||||
if (_heap1_->cmp(_heap1_->buffer[i], _heap2_->buffer[i]) != 0) \
|
||||
if (_heap1_->f_val->cmp(_heap1_->buffer[i], _heap2_->buffer[i]) != \
|
||||
0) \
|
||||
return false; \
|
||||
} \
|
||||
\
|
||||
@@ -513,14 +547,9 @@ struct cmc_callbacks_heap
|
||||
\
|
||||
int n = snprintf(str.s, cmc_string_len, cmc_string_fmt_heap, #SNAME, \
|
||||
#V, h_, h_->buffer, h_->capacity, h_->count, t, \
|
||||
h_->cmp, h_->alloc, h_->callbacks); \
|
||||
h_->f_val, h_->alloc, h_->callbacks); \
|
||||
\
|
||||
if (n < 0 || n == (int)cmc_string_len) \
|
||||
return (struct cmc_string){ 0 }; \
|
||||
\
|
||||
str.s[n] = '\0'; \
|
||||
\
|
||||
return str; \
|
||||
return n >= 0 ? str : (struct cmc_string){ 0 }; \
|
||||
} \
|
||||
\
|
||||
struct SNAME##_iter *PFX##_iter_new(struct SNAME *target) \
|
||||
@@ -699,7 +728,7 @@ struct cmc_callbacks_heap
|
||||
\
|
||||
int mod = _heap_->HO; \
|
||||
\
|
||||
while (C > 0 && _heap_->cmp(child, parent) * mod > 0) \
|
||||
while (C > 0 && _heap_->f_val->cmp(child, parent) * mod > 0) \
|
||||
{ \
|
||||
/* Swap between C (current element) and its parent */ \
|
||||
V tmp = _heap_->buffer[C]; \
|
||||
@@ -728,13 +757,17 @@ struct cmc_callbacks_heap
|
||||
\
|
||||
/* Determine if we swap with the left or right element */ \
|
||||
if (L < _heap_->count && \
|
||||
_heap_->cmp(_heap_->buffer[L], _heap_->buffer[C]) * mod > 0) \
|
||||
_heap_->f_val->cmp(_heap_->buffer[L], _heap_->buffer[C]) * \
|
||||
mod > \
|
||||
0) \
|
||||
{ \
|
||||
C = L; \
|
||||
} \
|
||||
\
|
||||
if (R < _heap_->count && \
|
||||
_heap_->cmp(_heap_->buffer[R], _heap_->buffer[C]) * mod > 0) \
|
||||
_heap_->f_val->cmp(_heap_->buffer[R], _heap_->buffer[C]) * \
|
||||
mod > \
|
||||
0) \
|
||||
{ \
|
||||
C = R; \
|
||||
} \
|
||||
|
||||
+200
-164
@@ -89,7 +89,7 @@ static const char *cmc_string_fmt_intervalheap = "struct %s<%s> "
|
||||
"capacity:%" PRIuMAX ", "
|
||||
"size:%" PRIuMAX ", "
|
||||
"count:%" PRIuMAX ", "
|
||||
"cmp:%p, "
|
||||
"f_val:%p, "
|
||||
"alloc:%p, "
|
||||
"callbacks:%p }";
|
||||
|
||||
@@ -121,115 +121,141 @@ struct cmc_callbacks_intervalheap
|
||||
/* -------------------------------------------------------------------------
|
||||
* Header
|
||||
* ------------------------------------------------------------------------- */
|
||||
#define CMC_GENERATE_INTERVALHEAP_HEADER(PFX, SNAME, V) \
|
||||
\
|
||||
/* Heap Structure */ \
|
||||
struct SNAME \
|
||||
{ \
|
||||
/* Dynamic array of nodes */ \
|
||||
struct SNAME##_node *buffer; \
|
||||
\
|
||||
/* Current array capacity (how many nodes can be stored) */ \
|
||||
size_t capacity; \
|
||||
\
|
||||
/* Current amount of nodes in the dynamic array */ \
|
||||
size_t size; \
|
||||
\
|
||||
/* Current amount of elements in the heap */ \
|
||||
size_t count; \
|
||||
\
|
||||
/* Element comparison function */ \
|
||||
int (*cmp)(V, V); \
|
||||
\
|
||||
/* Function that returns an iterator to the start of the heap */ \
|
||||
struct SNAME##_iter (*it_start)(struct SNAME *); \
|
||||
\
|
||||
/* Function that returns an iterator to the end of the heap */ \
|
||||
struct SNAME##_iter (*it_end)(struct SNAME *); \
|
||||
\
|
||||
/* Custom allocation functions */ \
|
||||
struct cmc_alloc_node *alloc; \
|
||||
\
|
||||
/* Custom callback functions */ \
|
||||
struct cmc_callbacks_intervalheap *callbacks; \
|
||||
}; \
|
||||
\
|
||||
/* Heap Node */ \
|
||||
struct SNAME##_node \
|
||||
{ \
|
||||
/* 0 - Value belonging to the MinHeap */ \
|
||||
/* 1 - Value belonging to the MaxHeap */ \
|
||||
V data[2]; \
|
||||
}; \
|
||||
\
|
||||
/* Heap Iterator */ \
|
||||
struct SNAME##_iter \
|
||||
{ \
|
||||
/* Target heap */ \
|
||||
struct SNAME *target; \
|
||||
\
|
||||
/* Cursor's position (index) */ \
|
||||
size_t cursor; \
|
||||
\
|
||||
/* If the iterator has reached the start of the iteration */ \
|
||||
bool start; \
|
||||
\
|
||||
/* If the iterator has reached the end of the iteration */ \
|
||||
bool end; \
|
||||
}; \
|
||||
\
|
||||
/* Collection Functions */ \
|
||||
/* Collection Allocation and Deallocation */ \
|
||||
struct SNAME *PFX##_new(size_t capacity, int (*compare)(V, V)); \
|
||||
struct SNAME *PFX##_new_custom( \
|
||||
size_t capacity, int (*compare)(V, V), struct cmc_alloc_node *alloc, \
|
||||
struct cmc_callbacks_intervalheap *callbacks); \
|
||||
void PFX##_clear(struct SNAME *_heap_, void (*deallocator)(V)); \
|
||||
void PFX##_free(struct SNAME *_heap_, void (*deallocator)(V)); \
|
||||
/* Customization of Allocation and Callbacks */ \
|
||||
void PFX##_customize(struct SNAME *_heap_, struct cmc_alloc_node *alloc, \
|
||||
struct cmc_callbacks_intervalheap *callbacks); \
|
||||
/* Collection Input and Output */ \
|
||||
bool PFX##_insert(struct SNAME *_heap_, V element); \
|
||||
bool PFX##_remove_max(struct SNAME *_heap_, V *result); \
|
||||
bool PFX##_remove_min(struct SNAME *_heap_, V *result); \
|
||||
/* Collection Update */ \
|
||||
bool PFX##_update_max(struct SNAME *_heap_, V element); \
|
||||
bool PFX##_update_min(struct SNAME *_heap_, V element); \
|
||||
/* Element Access */ \
|
||||
bool PFX##_max(struct SNAME *_heap_, V *value); \
|
||||
bool PFX##_min(struct SNAME *_heap_, V *value); \
|
||||
/* Collection State */ \
|
||||
bool PFX##_contains(struct SNAME *_heap_, V element); \
|
||||
bool PFX##_empty(struct SNAME *_heap_); \
|
||||
bool PFX##_full(struct SNAME *_heap_); \
|
||||
size_t PFX##_count(struct SNAME *_heap_); \
|
||||
size_t PFX##_capacity(struct SNAME *_heap_); \
|
||||
/* Collection Utility */ \
|
||||
bool PFX##_resize(struct SNAME *_heap_, size_t capacity); \
|
||||
struct SNAME *PFX##_copy_of(struct SNAME *_set_, V (*copy_func)(V)); \
|
||||
bool PFX##_equals(struct SNAME *_heap1_, struct SNAME *_heap2_); \
|
||||
struct cmc_string PFX##_to_string(struct SNAME *_heap_); \
|
||||
\
|
||||
/* Iterator Functions */ \
|
||||
/* Iterator Allocation and Deallocation */ \
|
||||
struct SNAME##_iter *PFX##_iter_new(struct SNAME *target); \
|
||||
void PFX##_iter_free(struct SNAME##_iter *iter); \
|
||||
/* Iterator Initialization */ \
|
||||
void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target); \
|
||||
/* Iterator State */ \
|
||||
bool PFX##_iter_start(struct SNAME##_iter *iter); \
|
||||
bool PFX##_iter_end(struct SNAME##_iter *iter); \
|
||||
/* Iterator Movement */ \
|
||||
void PFX##_iter_to_start(struct SNAME##_iter *iter); \
|
||||
void PFX##_iter_to_end(struct SNAME##_iter *iter); \
|
||||
bool PFX##_iter_next(struct SNAME##_iter *iter); \
|
||||
bool PFX##_iter_prev(struct SNAME##_iter *iter); \
|
||||
bool PFX##_iter_advance(struct SNAME##_iter *iter, size_t steps); \
|
||||
bool PFX##_iter_rewind(struct SNAME##_iter *iter, size_t steps); \
|
||||
bool PFX##_iter_go_to(struct SNAME##_iter *iter, size_t index); \
|
||||
/* Iterator Access */ \
|
||||
V PFX##_iter_value(struct SNAME##_iter *iter); \
|
||||
#define CMC_GENERATE_INTERVALHEAP_HEADER(PFX, SNAME, V) \
|
||||
\
|
||||
/* Heap Structure */ \
|
||||
struct SNAME \
|
||||
{ \
|
||||
/* Dynamic array of nodes */ \
|
||||
struct SNAME##_node *buffer; \
|
||||
\
|
||||
/* Current array capacity (how many nodes can be stored) */ \
|
||||
size_t capacity; \
|
||||
\
|
||||
/* Current amount of nodes in the dynamic array */ \
|
||||
size_t size; \
|
||||
\
|
||||
/* Current amount of elements in the heap */ \
|
||||
size_t count; \
|
||||
\
|
||||
/* Flags indicating errors or success */ \
|
||||
int flag; \
|
||||
\
|
||||
/* Value function table */ \
|
||||
struct SNAME##_ftab_val *f_val; \
|
||||
\
|
||||
/* Function that returns an iterator to the start of the heap */ \
|
||||
struct SNAME##_iter (*it_start)(struct SNAME *); \
|
||||
\
|
||||
/* Function that returns an iterator to the end of the heap */ \
|
||||
struct SNAME##_iter (*it_end)(struct SNAME *); \
|
||||
\
|
||||
/* Custom allocation functions */ \
|
||||
struct cmc_alloc_node *alloc; \
|
||||
\
|
||||
/* Custom callback functions */ \
|
||||
struct cmc_callbacks_intervalheap *callbacks; \
|
||||
}; \
|
||||
\
|
||||
/* Heap Node */ \
|
||||
struct SNAME##_node \
|
||||
{ \
|
||||
/* 0 - Value belonging to the MinHeap */ \
|
||||
/* 1 - Value belonging to the MaxHeap */ \
|
||||
V data[2]; \
|
||||
}; \
|
||||
\
|
||||
/* Value struct function table */ \
|
||||
struct SNAME##_ftab_val \
|
||||
{ \
|
||||
/* Comparator function */ \
|
||||
int (*cmp)(V, V); \
|
||||
\
|
||||
/* Copy function */ \
|
||||
V (*cpy)(V); \
|
||||
\
|
||||
/* To string function */ \
|
||||
bool (*str)(FILE *, V); \
|
||||
\
|
||||
/* Free from memory function */ \
|
||||
void (*free)(V); \
|
||||
\
|
||||
/* Hash function */ \
|
||||
size_t (*hash)(V); \
|
||||
\
|
||||
/* Priority function */ \
|
||||
int (*pri)(V, V); \
|
||||
}; \
|
||||
\
|
||||
/* Heap Iterator */ \
|
||||
struct SNAME##_iter \
|
||||
{ \
|
||||
/* Target heap */ \
|
||||
struct SNAME *target; \
|
||||
\
|
||||
/* Cursor's position (index) */ \
|
||||
size_t cursor; \
|
||||
\
|
||||
/* If the iterator has reached the start of the iteration */ \
|
||||
bool start; \
|
||||
\
|
||||
/* If the iterator has reached the end of the iteration */ \
|
||||
bool end; \
|
||||
}; \
|
||||
\
|
||||
/* Collection Functions */ \
|
||||
/* Collection Allocation and Deallocation */ \
|
||||
struct SNAME *PFX##_new(size_t capacity, struct SNAME##_ftab_val *f_val); \
|
||||
struct SNAME *PFX##_new_custom( \
|
||||
size_t capacity, struct SNAME##_ftab_val *f_val, \
|
||||
struct cmc_alloc_node *alloc, \
|
||||
struct cmc_callbacks_intervalheap *callbacks); \
|
||||
void PFX##_clear(struct SNAME *_heap_); \
|
||||
void PFX##_free(struct SNAME *_heap_); \
|
||||
/* Customization of Allocation and Callbacks */ \
|
||||
void PFX##_customize(struct SNAME *_heap_, struct cmc_alloc_node *alloc, \
|
||||
struct cmc_callbacks_intervalheap *callbacks); \
|
||||
/* Collection Input and Output */ \
|
||||
bool PFX##_insert(struct SNAME *_heap_, V element); \
|
||||
bool PFX##_remove_max(struct SNAME *_heap_, V *result); \
|
||||
bool PFX##_remove_min(struct SNAME *_heap_, V *result); \
|
||||
/* Collection Update */ \
|
||||
bool PFX##_update_max(struct SNAME *_heap_, V element); \
|
||||
bool PFX##_update_min(struct SNAME *_heap_, V element); \
|
||||
/* Element Access */ \
|
||||
bool PFX##_max(struct SNAME *_heap_, V *value); \
|
||||
bool PFX##_min(struct SNAME *_heap_, V *value); \
|
||||
/* Collection State */ \
|
||||
bool PFX##_contains(struct SNAME *_heap_, V element); \
|
||||
bool PFX##_empty(struct SNAME *_heap_); \
|
||||
bool PFX##_full(struct SNAME *_heap_); \
|
||||
size_t PFX##_count(struct SNAME *_heap_); \
|
||||
size_t PFX##_capacity(struct SNAME *_heap_); \
|
||||
/* Collection Utility */ \
|
||||
bool PFX##_resize(struct SNAME *_heap_, size_t capacity); \
|
||||
struct SNAME *PFX##_copy_of(struct SNAME *_set_); \
|
||||
bool PFX##_equals(struct SNAME *_heap1_, struct SNAME *_heap2_); \
|
||||
struct cmc_string PFX##_to_string(struct SNAME *_heap_); \
|
||||
\
|
||||
/* Iterator Functions */ \
|
||||
/* Iterator Allocation and Deallocation */ \
|
||||
struct SNAME##_iter *PFX##_iter_new(struct SNAME *target); \
|
||||
void PFX##_iter_free(struct SNAME##_iter *iter); \
|
||||
/* Iterator Initialization */ \
|
||||
void PFX##_iter_init(struct SNAME##_iter *iter, struct SNAME *target); \
|
||||
/* Iterator State */ \
|
||||
bool PFX##_iter_start(struct SNAME##_iter *iter); \
|
||||
bool PFX##_iter_end(struct SNAME##_iter *iter); \
|
||||
/* Iterator Movement */ \
|
||||
void PFX##_iter_to_start(struct SNAME##_iter *iter); \
|
||||
void PFX##_iter_to_end(struct SNAME##_iter *iter); \
|
||||
bool PFX##_iter_next(struct SNAME##_iter *iter); \
|
||||
bool PFX##_iter_prev(struct SNAME##_iter *iter); \
|
||||
bool PFX##_iter_advance(struct SNAME##_iter *iter, size_t steps); \
|
||||
bool PFX##_iter_rewind(struct SNAME##_iter *iter, size_t steps); \
|
||||
bool PFX##_iter_go_to(struct SNAME##_iter *iter, size_t index); \
|
||||
/* Iterator Access */ \
|
||||
V PFX##_iter_value(struct SNAME##_iter *iter); \
|
||||
size_t PFX##_iter_index(struct SNAME##_iter *iter);
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
@@ -245,13 +271,16 @@ struct cmc_callbacks_intervalheap
|
||||
static struct SNAME##_iter PFX##_impl_it_start(struct SNAME *_heap_); \
|
||||
static struct SNAME##_iter PFX##_impl_it_end(struct SNAME *_heap_); \
|
||||
\
|
||||
struct SNAME *PFX##_new(size_t capacity, int (*compare)(V, V)) \
|
||||
struct SNAME *PFX##_new(size_t capacity, struct SNAME##_ftab_val *f_val) \
|
||||
{ \
|
||||
struct cmc_alloc_node *alloc = &cmc_alloc_node_default; \
|
||||
\
|
||||
if (capacity == 0 || capacity == UINT64_MAX) \
|
||||
return NULL; \
|
||||
\
|
||||
if (!f_val) \
|
||||
return NULL; \
|
||||
\
|
||||
struct SNAME *_heap_ = alloc->malloc(sizeof(struct SNAME)); \
|
||||
\
|
||||
if (!_heap_) \
|
||||
@@ -273,24 +302,27 @@ struct cmc_callbacks_intervalheap
|
||||
_heap_->capacity = capacity; \
|
||||
_heap_->size = 0; \
|
||||
_heap_->count = 0; \
|
||||
_heap_->cmp = compare; \
|
||||
\
|
||||
_heap_->it_start = PFX##_impl_it_start; \
|
||||
_heap_->it_end = PFX##_impl_it_end; \
|
||||
\
|
||||
_heap_->flag = cmc_flags.OK; \
|
||||
_heap_->f_val = f_val; \
|
||||
_heap_->alloc = alloc; \
|
||||
_heap_->callbacks = NULL; \
|
||||
_heap_->it_start = PFX##_impl_it_start; \
|
||||
_heap_->it_end = PFX##_impl_it_end; \
|
||||
\
|
||||
return _heap_; \
|
||||
} \
|
||||
\
|
||||
struct SNAME *PFX##_new_custom( \
|
||||
size_t capacity, int (*compare)(V, V), struct cmc_alloc_node *alloc, \
|
||||
size_t capacity, struct SNAME##_ftab_val *f_val, \
|
||||
struct cmc_alloc_node *alloc, \
|
||||
struct cmc_callbacks_intervalheap *callbacks) \
|
||||
{ \
|
||||
if (capacity == 0 || capacity == UINT64_MAX) \
|
||||
return NULL; \
|
||||
\
|
||||
if (!f_val) \
|
||||
return NULL; \
|
||||
\
|
||||
if (!alloc) \
|
||||
alloc = &cmc_alloc_node_default; \
|
||||
\
|
||||
@@ -315,24 +347,23 @@ struct cmc_callbacks_intervalheap
|
||||
_heap_->capacity = capacity; \
|
||||
_heap_->size = 0; \
|
||||
_heap_->count = 0; \
|
||||
_heap_->cmp = compare; \
|
||||
\
|
||||
_heap_->it_start = PFX##_impl_it_start; \
|
||||
_heap_->it_end = PFX##_impl_it_end; \
|
||||
\
|
||||
_heap_->flag = cmc_flags.OK; \
|
||||
_heap_->f_val = f_val; \
|
||||
_heap_->alloc = alloc; \
|
||||
_heap_->callbacks = callbacks; \
|
||||
_heap_->it_start = PFX##_impl_it_start; \
|
||||
_heap_->it_end = PFX##_impl_it_end; \
|
||||
\
|
||||
return _heap_; \
|
||||
} \
|
||||
\
|
||||
void PFX##_clear(struct SNAME *_heap_, void (*deallocator)(V)) \
|
||||
void PFX##_clear(struct SNAME *_heap_) \
|
||||
{ \
|
||||
if (deallocator) \
|
||||
if (_heap_->f_val->free) \
|
||||
{ \
|
||||
for (size_t i = 0; i < _heap_->count; i++) \
|
||||
{ \
|
||||
deallocator(_heap_->buffer[i / 2].data[i % 2]); \
|
||||
_heap_->f_val->free(_heap_->buffer[i / 2].data[i % 2]); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
@@ -342,13 +373,13 @@ struct cmc_callbacks_intervalheap
|
||||
_heap_->count = 0; \
|
||||
} \
|
||||
\
|
||||
void PFX##_free(struct SNAME *_heap_, void (*deallocator)(V)) \
|
||||
void PFX##_free(struct SNAME *_heap_) \
|
||||
{ \
|
||||
if (deallocator) \
|
||||
if (_heap_->f_val->free) \
|
||||
{ \
|
||||
for (size_t i = 0; i < _heap_->count; i++) \
|
||||
{ \
|
||||
deallocator(_heap_->buffer[i / 2].data[i % 2]); \
|
||||
_heap_->f_val->free(_heap_->buffer[i / 2].data[i % 2]); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
@@ -385,20 +416,19 @@ struct cmc_callbacks_intervalheap
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
struct SNAME##_node *curr_node = \
|
||||
&(_heap_->buffer[_heap_->size - 1]); \
|
||||
struct SNAME##_node *node = &(_heap_->buffer[_heap_->size - 1]); \
|
||||
\
|
||||
/* Decide if the new element goes into the MinHeap or MaxHeap */ \
|
||||
if (_heap_->cmp(curr_node->data[0], element) > 0) \
|
||||
if (_heap_->f_val->cmp(node->data[0], element) > 0) \
|
||||
{ \
|
||||
/* Swap current value and add new element to the MinHeap */ \
|
||||
curr_node->data[1] = curr_node->data[0]; \
|
||||
curr_node->data[0] = element; \
|
||||
node->data[1] = node->data[0]; \
|
||||
node->data[0] = element; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
/* No need to swap and add the new element to the MaxHeap */ \
|
||||
curr_node->data[1] = element; \
|
||||
node->data[1] = element; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
@@ -411,9 +441,9 @@ struct cmc_callbacks_intervalheap
|
||||
struct SNAME##_node *parent = \
|
||||
&(_heap_->buffer[(_heap_->size - 1) / 2]); \
|
||||
\
|
||||
if (_heap_->cmp(parent->data[0], element) > 0) \
|
||||
if (_heap_->f_val->cmp(parent->data[0], element) > 0) \
|
||||
PFX##_impl_float_up_min(_heap_); \
|
||||
else if (_heap_->cmp(parent->data[1], element) < 0) \
|
||||
else if (_heap_->f_val->cmp(parent->data[1], element) < 0) \
|
||||
PFX##_impl_float_up_max(_heap_); \
|
||||
/* else no float up required */ \
|
||||
\
|
||||
@@ -519,7 +549,7 @@ struct cmc_callbacks_intervalheap
|
||||
{ \
|
||||
_heap_->buffer[0].data[0] = element; \
|
||||
} \
|
||||
else if (_heap_->cmp(element, _heap_->buffer[0].data[0]) < 0) \
|
||||
else if (_heap_->f_val->cmp(element, _heap_->buffer[0].data[0]) < 0) \
|
||||
{ \
|
||||
/* Corner case: we are updating the Max value but it is less */ \
|
||||
/* than the Min value */ \
|
||||
@@ -548,7 +578,7 @@ struct cmc_callbacks_intervalheap
|
||||
{ \
|
||||
_heap_->buffer[0].data[0] = element; \
|
||||
} \
|
||||
else if (_heap_->cmp(element, _heap_->buffer[0].data[1]) > 0) \
|
||||
else if (_heap_->f_val->cmp(element, _heap_->buffer[0].data[1]) > 0) \
|
||||
{ \
|
||||
/* Corner case: we are updating the Min value but it is greater */ \
|
||||
/* than the Max value. */ \
|
||||
@@ -597,7 +627,8 @@ struct cmc_callbacks_intervalheap
|
||||
{ \
|
||||
for (size_t i = 0; i < _heap_->count; i++) \
|
||||
{ \
|
||||
if (_heap_->cmp(_heap_->buffer[i / 2].data[i % 2], element) == 0) \
|
||||
if (_heap_->f_val->cmp(_heap_->buffer[i / 2].data[i % 2], \
|
||||
element) == 0) \
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
@@ -650,7 +681,7 @@ struct cmc_callbacks_intervalheap
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
struct SNAME *PFX##_copy_of(struct SNAME *_heap_, V (*copy_func)(V)) \
|
||||
struct SNAME *PFX##_copy_of(struct SNAME *_heap_) \
|
||||
{ \
|
||||
struct SNAME *result = _heap_->alloc->malloc(sizeof(struct SNAME)); \
|
||||
\
|
||||
@@ -668,11 +699,11 @@ struct cmc_callbacks_intervalheap
|
||||
return NULL; \
|
||||
} \
|
||||
\
|
||||
if (copy_func) \
|
||||
if (_heap_->f_val->cpy) \
|
||||
{ \
|
||||
for (size_t i = 0; i < _heap_->count; i++) \
|
||||
result->buffer[i / 2].data[i % 2] = \
|
||||
copy_func(_heap_->buffer[i / 2].data[i % 2]); \
|
||||
_heap_->f_val->cpy(_heap_->buffer[i / 2].data[i % 2]); \
|
||||
} \
|
||||
else \
|
||||
memcpy(result->buffer, _heap_->buffer, \
|
||||
@@ -694,7 +725,7 @@ struct cmc_callbacks_intervalheap
|
||||
V element1 = _heap1_->buffer[i / 2].data[i % 2]; \
|
||||
V element2 = _heap2_->buffer[i / 2].data[i % 2]; \
|
||||
\
|
||||
if (_heap1_->cmp(element1, element2) == 0) \
|
||||
if (_heap1_->f_val->cmp(element1, element2) == 0) \
|
||||
return true; \
|
||||
} \
|
||||
\
|
||||
@@ -708,14 +739,9 @@ struct cmc_callbacks_intervalheap
|
||||
\
|
||||
int n = snprintf(str.s, cmc_string_len, cmc_string_fmt_intervalheap, \
|
||||
#SNAME, #V, h_, h_->buffer, h_->capacity, h_->size, \
|
||||
h_->count, h_->cmp, h_->alloc, h_->callbacks); \
|
||||
h_->count, h_->f_val, h_->alloc, h_->callbacks); \
|
||||
\
|
||||
if (n < 0 || n == (int)cmc_string_len) \
|
||||
return (struct cmc_string){ 0 }; \
|
||||
\
|
||||
str.s[n] = '\0'; \
|
||||
\
|
||||
return str; \
|
||||
return n >= 0 ? str : (struct cmc_string){ 0 }; \
|
||||
} \
|
||||
\
|
||||
struct SNAME##_iter *PFX##_iter_new(struct SNAME *target) \
|
||||
@@ -900,7 +926,8 @@ struct cmc_callbacks_intervalheap
|
||||
{ \
|
||||
/* In this case, the current node has no MaxHeap value so */ \
|
||||
/* we instead compare with the MinHeap value */ \
|
||||
if (_heap_->cmp(curr_node->data[0], parent->data[1]) < 0) \
|
||||
if (_heap_->f_val->cmp(curr_node->data[0], parent->data[1]) < \
|
||||
0) \
|
||||
break; \
|
||||
\
|
||||
/* Since the comparison above passed now we need to swap */ \
|
||||
@@ -914,7 +941,8 @@ struct cmc_callbacks_intervalheap
|
||||
else \
|
||||
{ \
|
||||
/* Usual case, just compare both MaxHeap values */ \
|
||||
if (_heap_->cmp(curr_node->data[1], parent->data[1]) < 0) \
|
||||
if (_heap_->f_val->cmp(curr_node->data[1], parent->data[1]) < \
|
||||
0) \
|
||||
break; \
|
||||
\
|
||||
/* Swap with parent and repeat */ \
|
||||
@@ -943,7 +971,7 @@ struct cmc_callbacks_intervalheap
|
||||
\
|
||||
struct SNAME##_node *parent = &(_heap_->buffer[P_index]); \
|
||||
\
|
||||
if (_heap_->cmp(curr_node->data[0], parent->data[0]) >= 0) \
|
||||
if (_heap_->f_val->cmp(curr_node->data[0], parent->data[0]) >= 0) \
|
||||
break; \
|
||||
\
|
||||
/* Swap with parent and repeat */ \
|
||||
@@ -986,11 +1014,13 @@ struct cmc_callbacks_intervalheap
|
||||
/* then do the comparison with the MinHeap value */ \
|
||||
if (R_index == _heap_->size - 1 && \
|
||||
PFX##_count(_heap_) % 2 != 0) \
|
||||
child = _heap_->cmp(L->data[1], R->data[0]) > 0 ? L_index \
|
||||
: R_index; \
|
||||
child = _heap_->f_val->cmp(L->data[1], R->data[0]) > 0 \
|
||||
? L_index \
|
||||
: R_index; \
|
||||
else \
|
||||
child = _heap_->cmp(L->data[1], R->data[1]) > 0 ? L_index \
|
||||
: R_index; \
|
||||
child = _heap_->f_val->cmp(L->data[1], R->data[1]) > 0 \
|
||||
? L_index \
|
||||
: R_index; \
|
||||
} \
|
||||
/* Pick the only one available */ \
|
||||
else \
|
||||
@@ -1005,7 +1035,8 @@ struct cmc_callbacks_intervalheap
|
||||
/* Odd case, compare with MinHeap value */ \
|
||||
/* If current value is not less than the child node's */ \
|
||||
/* value it is done */ \
|
||||
if (_heap_->cmp(curr_node->data[1], child_node->data[0]) >= 0) \
|
||||
if (_heap_->f_val->cmp(curr_node->data[1], \
|
||||
child_node->data[0]) >= 0) \
|
||||
break; \
|
||||
\
|
||||
/* Otherwise swap and continue */ \
|
||||
@@ -1017,7 +1048,8 @@ struct cmc_callbacks_intervalheap
|
||||
{ \
|
||||
/* If current value is not less than the child node's */ \
|
||||
/* value it is done */ \
|
||||
if (_heap_->cmp(curr_node->data[1], child_node->data[1]) >= 0) \
|
||||
if (_heap_->f_val->cmp(curr_node->data[1], \
|
||||
child_node->data[1]) >= 0) \
|
||||
break; \
|
||||
\
|
||||
/* Otherwise swap and continue */ \
|
||||
@@ -1027,7 +1059,8 @@ struct cmc_callbacks_intervalheap
|
||||
\
|
||||
/* Check if the MinHeap and MaxHeap values need to be */ \
|
||||
/* swapped */ \
|
||||
if (_heap_->cmp(child_node->data[0], child_node->data[1]) > 0) \
|
||||
if (_heap_->f_val->cmp(child_node->data[0], \
|
||||
child_node->data[1]) > 0) \
|
||||
{ \
|
||||
/* Swap because the MinHeap value is greater than the */ \
|
||||
/* MaxHeap value */ \
|
||||
@@ -1067,8 +1100,9 @@ struct cmc_callbacks_intervalheap
|
||||
struct SNAME##_node *L = &(_heap_->buffer[L_index]); \
|
||||
struct SNAME##_node *R = &(_heap_->buffer[R_index]); \
|
||||
\
|
||||
child = _heap_->cmp(L->data[0], R->data[0]) < 0 ? L_index \
|
||||
: R_index; \
|
||||
child = _heap_->f_val->cmp(L->data[0], R->data[0]) < 0 \
|
||||
? L_index \
|
||||
: R_index; \
|
||||
} \
|
||||
/* Pick the only one available */ \
|
||||
else \
|
||||
@@ -1078,7 +1112,8 @@ struct cmc_callbacks_intervalheap
|
||||
\
|
||||
/* If current value is smaller than the child node's value, it */ \
|
||||
/* is done */ \
|
||||
if (_heap_->cmp(curr_node->data[0], child_node->data[0]) < 0) \
|
||||
if (_heap_->f_val->cmp(curr_node->data[0], child_node->data[0]) < \
|
||||
0) \
|
||||
break; \
|
||||
\
|
||||
/* Otherwise swap and continue */ \
|
||||
@@ -1090,7 +1125,8 @@ struct cmc_callbacks_intervalheap
|
||||
/* MaxHeap values need to be swapped */ \
|
||||
if (child != _heap_->size - 1 || PFX##_count(_heap_) % 2 == 0) \
|
||||
{ \
|
||||
if (_heap_->cmp(child_node->data[0], child_node->data[1]) > 0) \
|
||||
if (_heap_->f_val->cmp(child_node->data[0], \
|
||||
child_node->data[1]) > 0) \
|
||||
{ \
|
||||
/* Swap because the MinHeap value is greater than the */ \
|
||||
/* MaxHeap value */ \
|
||||
|
||||
Reference in new issue
Block a user