Change priority_heap to accept "less_fn"
All checks were successful
Run Unit Tests / build-and-run-unit-tests (push) Successful in 3s
All checks were successful
Run Unit Tests / build-and-run-unit-tests (push) Successful in 3s
This allows for reverse order in the priority heap by using a "more_fn" in place of a "less fn".
This commit is contained in:
parent
d815f67b2d
commit
9e95c5e292
3 changed files with 101 additions and 6 deletions
|
@ -26,6 +26,7 @@ void simple_archiver_priority_heap_internal_realloc(
|
||||||
|
|
||||||
new_priority_heap->capacity = (*priority_heap)->capacity * 2;
|
new_priority_heap->capacity = (*priority_heap)->capacity * 2;
|
||||||
new_priority_heap->size = 0;
|
new_priority_heap->size = 0;
|
||||||
|
new_priority_heap->less_fn = (*priority_heap)->less_fn;
|
||||||
|
|
||||||
new_priority_heap->nodes =
|
new_priority_heap->nodes =
|
||||||
calloc(new_priority_heap->capacity, sizeof(SDArchiverPHNode));
|
calloc(new_priority_heap->capacity, sizeof(SDArchiverPHNode));
|
||||||
|
@ -45,11 +46,30 @@ void simple_archiver_priority_heap_internal_realloc(
|
||||||
*priority_heap = new_priority_heap;
|
*priority_heap = new_priority_heap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int simple_archiver_priority_heap_default_less(long long a, long long b) {
|
||||||
|
return a < b ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
SDArchiverPHeap *simple_archiver_priority_heap_init(void) {
|
SDArchiverPHeap *simple_archiver_priority_heap_init(void) {
|
||||||
SDArchiverPHeap *priority_heap = malloc(sizeof(SDArchiverPHeap));
|
SDArchiverPHeap *priority_heap = malloc(sizeof(SDArchiverPHeap));
|
||||||
|
|
||||||
priority_heap->capacity = SC_SA_DS_PRIORITY_HEAP_START_SIZE;
|
priority_heap->capacity = SC_SA_DS_PRIORITY_HEAP_START_SIZE;
|
||||||
priority_heap->size = 0;
|
priority_heap->size = 0;
|
||||||
|
priority_heap->less_fn = simple_archiver_priority_heap_default_less;
|
||||||
|
|
||||||
|
priority_heap->nodes =
|
||||||
|
calloc(priority_heap->capacity, sizeof(SDArchiverPHNode));
|
||||||
|
|
||||||
|
return priority_heap;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDArchiverPHeap *simple_archiver_priority_heap_init_less_fn(
|
||||||
|
int (*less_fn)(long long, long long)) {
|
||||||
|
SDArchiverPHeap *priority_heap = malloc(sizeof(SDArchiverPHeap));
|
||||||
|
|
||||||
|
priority_heap->capacity = SC_SA_DS_PRIORITY_HEAP_START_SIZE;
|
||||||
|
priority_heap->size = 0;
|
||||||
|
priority_heap->less_fn = less_fn;
|
||||||
|
|
||||||
priority_heap->nodes =
|
priority_heap->nodes =
|
||||||
calloc(priority_heap->capacity, sizeof(SDArchiverPHNode));
|
calloc(priority_heap->capacity, sizeof(SDArchiverPHNode));
|
||||||
|
@ -91,7 +111,10 @@ void simple_archiver_priority_heap_insert(SDArchiverPHeap **priority_heap,
|
||||||
|
|
||||||
unsigned int hole = (*priority_heap)->size + 1;
|
unsigned int hole = (*priority_heap)->size + 1;
|
||||||
|
|
||||||
while (hole > 1 && priority < (*priority_heap)->nodes[hole / 2].priority) {
|
while (hole > 1 &&
|
||||||
|
(*priority_heap)
|
||||||
|
->less_fn(priority,
|
||||||
|
(*priority_heap)->nodes[hole / 2].priority) != 0) {
|
||||||
(*priority_heap)->nodes[hole] = (*priority_heap)->nodes[hole / 2];
|
(*priority_heap)->nodes[hole] = (*priority_heap)->nodes[hole / 2];
|
||||||
hole /= 2;
|
hole /= 2;
|
||||||
}
|
}
|
||||||
|
@ -127,12 +150,15 @@ void *simple_archiver_priority_heap_pop(SDArchiverPHeap *priority_heap) {
|
||||||
while (hole * 2 + 1 <= priority_heap->size) {
|
while (hole * 2 + 1 <= priority_heap->size) {
|
||||||
if (priority_heap->nodes[hole * 2].is_valid != 0 &&
|
if (priority_heap->nodes[hole * 2].is_valid != 0 &&
|
||||||
priority_heap->nodes[hole * 2 + 1].is_valid != 0) {
|
priority_heap->nodes[hole * 2 + 1].is_valid != 0) {
|
||||||
if (end.priority < priority_heap->nodes[hole * 2].priority &&
|
if (priority_heap->less_fn(
|
||||||
end.priority < priority_heap->nodes[hole * 2 + 1].priority) {
|
end.priority, priority_heap->nodes[hole * 2].priority) != 0 &&
|
||||||
|
priority_heap->less_fn(
|
||||||
|
end.priority, priority_heap->nodes[hole * 2 + 1].priority) != 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (priority_heap->nodes[hole * 2].priority <
|
if (priority_heap->less_fn(priority_heap->nodes[hole * 2].priority,
|
||||||
priority_heap->nodes[hole * 2 + 1].priority) {
|
priority_heap->nodes[hole * 2 + 1].priority) !=
|
||||||
|
0) {
|
||||||
priority_heap->nodes[hole] = priority_heap->nodes[hole * 2];
|
priority_heap->nodes[hole] = priority_heap->nodes[hole * 2];
|
||||||
hole = hole * 2;
|
hole = hole * 2;
|
||||||
} else {
|
} else {
|
||||||
|
@ -140,7 +166,8 @@ void *simple_archiver_priority_heap_pop(SDArchiverPHeap *priority_heap) {
|
||||||
hole = hole * 2 + 1;
|
hole = hole * 2 + 1;
|
||||||
}
|
}
|
||||||
} else if (priority_heap->nodes[hole * 2].is_valid != 0) {
|
} else if (priority_heap->nodes[hole * 2].is_valid != 0) {
|
||||||
if (end.priority < priority_heap->nodes[hole * 2].priority) {
|
if (priority_heap->less_fn(
|
||||||
|
end.priority, priority_heap->nodes[hole * 2].priority) != 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
priority_heap->nodes[hole] = priority_heap->nodes[hole * 2];
|
priority_heap->nodes[hole] = priority_heap->nodes[hole * 2];
|
||||||
|
|
|
@ -33,9 +33,16 @@ typedef struct SDArchiverPHeap {
|
||||||
SDArchiverPHNode *nodes;
|
SDArchiverPHNode *nodes;
|
||||||
unsigned long long capacity;
|
unsigned long long capacity;
|
||||||
unsigned long long size;
|
unsigned long long size;
|
||||||
|
int (*less_fn)(long long, long long);
|
||||||
} SDArchiverPHeap;
|
} SDArchiverPHeap;
|
||||||
|
|
||||||
|
/// Default "less" function to determine if a has higher priority than b.
|
||||||
|
/// Returns non-zero if "less".
|
||||||
|
int simple_archiver_priority_heap_default_less(long long a, long long b);
|
||||||
|
|
||||||
SDArchiverPHeap *simple_archiver_priority_heap_init(void);
|
SDArchiverPHeap *simple_archiver_priority_heap_init(void);
|
||||||
|
SDArchiverPHeap *simple_archiver_priority_heap_init_less_fn(
|
||||||
|
int (*less_fn)(long long, long long));
|
||||||
void simple_archiver_priority_heap_free(SDArchiverPHeap **priority_heap);
|
void simple_archiver_priority_heap_free(SDArchiverPHeap **priority_heap);
|
||||||
|
|
||||||
/// If data_cleanup_fn is NULL, then "free()" is used on data when freed.
|
/// If data_cleanup_fn is NULL, then "free()" is used on data when freed.
|
||||||
|
|
|
@ -61,6 +61,8 @@ int get_three_fn(void *data, __attribute__((unused)) void *ud) {
|
||||||
return strcmp(data, "three") == 0 ? 1 : 0;
|
return strcmp(data, "three") == 0 ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int more_fn(long long a, long long b) { return a > b ? 1 : 0; }
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
// Test LinkedList.
|
// Test LinkedList.
|
||||||
{
|
{
|
||||||
|
@ -259,6 +261,65 @@ int main(void) {
|
||||||
simple_archiver_priority_heap_insert(&priority_heap, idx, data, NULL);
|
simple_archiver_priority_heap_insert(&priority_heap, idx, data, NULL);
|
||||||
}
|
}
|
||||||
simple_archiver_priority_heap_free(&priority_heap);
|
simple_archiver_priority_heap_free(&priority_heap);
|
||||||
|
|
||||||
|
// Reverse priority.
|
||||||
|
priority_heap = simple_archiver_priority_heap_init_less_fn(more_fn);
|
||||||
|
|
||||||
|
for (unsigned int idx = 0; idx < max; ++idx) {
|
||||||
|
unsigned int *data = malloc(sizeof(unsigned int));
|
||||||
|
*data = idx;
|
||||||
|
simple_archiver_priority_heap_insert(&priority_heap, idx, data, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned int idx = max; idx-- > 0;) {
|
||||||
|
unsigned int *data = simple_archiver_priority_heap_top(priority_heap);
|
||||||
|
CHECK_TRUE(*data == idx);
|
||||||
|
data = simple_archiver_priority_heap_pop(priority_heap);
|
||||||
|
CHECK_TRUE(*data == idx);
|
||||||
|
free(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
simple_archiver_priority_heap_free(&priority_heap);
|
||||||
|
|
||||||
|
// Insert in random order with reverse-priority-heap.
|
||||||
|
priority_heap = simple_archiver_priority_heap_init_less_fn(more_fn);
|
||||||
|
array = malloc(sizeof(unsigned int) * max);
|
||||||
|
for (unsigned int idx = 0; idx < max; ++idx) {
|
||||||
|
array[idx] = idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deterministic randomization.
|
||||||
|
for (unsigned int idx = max - 1; idx-- > 0;) {
|
||||||
|
unsigned int other_idx = simple_archiver_algo_lcg_defaults(idx) %
|
||||||
|
(unsigned long long)(idx + 1);
|
||||||
|
if (idx != other_idx) {
|
||||||
|
unsigned int temp = array[max - 1];
|
||||||
|
array[max - 1] = array[other_idx];
|
||||||
|
array[other_idx] = temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert the deterministically randomized array.
|
||||||
|
for (unsigned int idx = 0; idx < max; ++idx) {
|
||||||
|
simple_archiver_priority_heap_insert(&priority_heap, array[idx],
|
||||||
|
array + idx, no_free_fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned int idx = max; idx-- > 0;) {
|
||||||
|
unsigned int *data = simple_archiver_priority_heap_top(priority_heap);
|
||||||
|
CHECK_TRUE(*data == idx);
|
||||||
|
if (*data != idx) {
|
||||||
|
printf("idx is %u, data is %u\n", idx, *data);
|
||||||
|
}
|
||||||
|
data = simple_archiver_priority_heap_pop(priority_heap);
|
||||||
|
CHECK_TRUE(*data == idx);
|
||||||
|
if (*data != idx) {
|
||||||
|
printf("idx is %u, data is %u\n", idx, *data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(array);
|
||||||
|
|
||||||
|
simple_archiver_priority_heap_free(&priority_heap);
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Checks checked: %u\n", checks_checked);
|
printf("Checks checked: %u\n", checks_checked);
|
||||||
|
|
Loading…
Reference in a new issue