new_priority_heap->capacity = (*priority_heap)->capacity * 2;
new_priority_heap->size = 0;
+ new_priority_heap->less_fn = (*priority_heap)->less_fn;
new_priority_heap->nodes =
calloc(new_priority_heap->capacity, sizeof(SDArchiverPHNode));
*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 *priority_heap = malloc(sizeof(SDArchiverPHeap));
priority_heap->capacity = SC_SA_DS_PRIORITY_HEAP_START_SIZE;
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 =
calloc(priority_heap->capacity, sizeof(SDArchiverPHNode));
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];
hole /= 2;
}
while (hole * 2 + 1 <= priority_heap->size) {
if (priority_heap->nodes[hole * 2].is_valid != 0 &&
priority_heap->nodes[hole * 2 + 1].is_valid != 0) {
- if (end.priority < priority_heap->nodes[hole * 2].priority &&
- end.priority < priority_heap->nodes[hole * 2 + 1].priority) {
+ if (priority_heap->less_fn(
+ end.priority, priority_heap->nodes[hole * 2].priority) != 0 &&
+ priority_heap->less_fn(
+ end.priority, priority_heap->nodes[hole * 2 + 1].priority) != 0) {
break;
}
- if (priority_heap->nodes[hole * 2].priority <
- priority_heap->nodes[hole * 2 + 1].priority) {
+ if (priority_heap->less_fn(priority_heap->nodes[hole * 2].priority,
+ priority_heap->nodes[hole * 2 + 1].priority) !=
+ 0) {
priority_heap->nodes[hole] = priority_heap->nodes[hole * 2];
hole = hole * 2;
} else {
hole = hole * 2 + 1;
}
} 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;
}
priority_heap->nodes[hole] = priority_heap->nodes[hole * 2];
SDArchiverPHNode *nodes;
unsigned long long capacity;
unsigned long long size;
+ int (*less_fn)(long long, long long);
} 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_less_fn(
+ int (*less_fn)(long long, long long));
void simple_archiver_priority_heap_free(SDArchiverPHeap **priority_heap);
/// If data_cleanup_fn is NULL, then "free()" is used on data when freed.
return strcmp(data, "three") == 0 ? 1 : 0;
}
+int more_fn(long long a, long long b) { return a > b ? 1 : 0; }
+
int main(void) {
// Test LinkedList.
{
simple_archiver_priority_heap_insert(&priority_heap, idx, data, NULL);
}
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);