diff --git a/src/heap/vieter_heap.c b/src/heap/vieter_heap.c index f6d3eab..45f9e01 100644 --- a/src/heap/vieter_heap.c +++ b/src/heap/vieter_heap.c @@ -56,14 +56,6 @@ vieter_heap_error vieter_heap_pop(void **out, vieter_heap *heap) { return vieter_heap_empty; } - if (heap->tree->order == 0 && heap->tree->ptr.next_tree == NULL) { - *out = heap->tree->data; - vieter_heap_tree_free(heap->tree); - heap->tree = NULL; - - return vieter_heap_ok; - } - heap->tree = vieter_heap_tree_pop(out, heap->tree); return vieter_heap_ok; diff --git a/src/heap/vieter_heap_tree.c b/src/heap/vieter_heap_tree.c index 56907a8..ff1ee66 100644 --- a/src/heap/vieter_heap_tree.c +++ b/src/heap/vieter_heap_tree.c @@ -167,6 +167,9 @@ vieter_heap_node *vieter_heap_tree_pop(void **out, vieter_heap_node *tree) { return original_root; } + // Each child has a pointer to its sibling with the next largest order. If we + // want to convert this list of children into their own tree, these pointers + // have to be reversed. previous_tree = tree_to_pop->largest_order; vieter_heap_node_free(tree_to_pop); diff --git a/test/heap/test_heap.c b/test/heap/test_heap.c index e136d87..ad73b8c 100644 --- a/test/heap/test_heap.c +++ b/test/heap/test_heap.c @@ -5,7 +5,7 @@ #define TEST_SIZE(heap, size) \ TEST_CHECK(vieter_heap_size(heap) == size); \ - TEST_MSG("Size: %zu", vieter_heap_size(heap)) + TEST_MSG("Size: %zu, expected: %lu", vieter_heap_size(heap), (uint64_t)size) void test_init() { vieter_heap *heap = vieter_heap_init(); @@ -14,25 +14,6 @@ void test_init() { vieter_heap_free(heap); } -void test_merge_same_order() { - vieter_heap_node *root_a = vieter_heap_node_init(); - root_a->key = 1; - root_a->order = 0; - - vieter_heap_node *root_b = vieter_heap_node_init(); - root_b->key = 2; - root_b->order = 0; - - vieter_heap_node *merged = vieter_heap_tree_merge_same_order(root_a, root_b); - - TEST_CHECK(merged == root_a); - TEST_CHECK(merged->key == 1); - TEST_CHECK(merged->largest_order == root_b); - TEST_CHECK(merged->ptr.next_largest_order == NULL); - - vieter_heap_tree_free(merged); -} - void test_insert() { vieter_heap *heap = vieter_heap_init(); TEST_SIZE(heap, 0); @@ -52,6 +33,36 @@ void test_insert() { vieter_heap_free(heap); } +void test_insert_random() { + srand(1); + + vieter_heap *heap = vieter_heap_init(); + TEST_SIZE(heap, 0); + + uint64_t num = rand(); + uint64_t smallest = num; + + void *data = NULL; + + for (uint64_t i = 0; i < 5000; i++) { + vieter_heap_insert(heap, num, (void *)num); + TEST_SIZE(heap, i + 1); + + if (num < smallest) { + smallest = num; + } + + TEST_CHECK(vieter_heap_peek(&data, heap) == vieter_heap_ok); + TEST_CHECK(data == (void *)smallest); + + data = NULL; + + num = rand(); + } + + vieter_heap_free(heap); +} + void test_pop() { vieter_heap *heap = vieter_heap_init(); TEST_SIZE(heap, 0); @@ -80,7 +91,7 @@ void test_pop() { int uint64_t_compare(const void *a, const void *b) { if ((*(uint64_t *)a) < (*(uint64_t *)b)) { return -1; - } else if ((*(uint64_t *)a) < (*(uint64_t *)b)) { + } else if ((*(uint64_t *)a) > (*(uint64_t *)b)) { return 1; } else { return 0; @@ -88,14 +99,16 @@ int uint64_t_compare(const void *a, const void *b) { } void test_pop_random() { + const uint64_t n = 29; + srand(0); vieter_heap *heap = vieter_heap_init(); - uint64_t *numbers = malloc(500 * sizeof(uint64_t)); + uint64_t *numbers = malloc(n * sizeof(uint64_t)); uint64_t num; - for (uint64_t i = 0; i < 500; i++) { + for (uint64_t i = 0; i < n; i++) { num = rand(); vieter_heap_insert(heap, num, (void *)num); TEST_SIZE(heap, i + 1); @@ -104,19 +117,19 @@ void test_pop_random() { } - qsort(numbers, 500, sizeof(uint64_t), uint64_t_compare); + qsort(numbers, n, sizeof(uint64_t), uint64_t_compare); void *data = NULL; - for (uint64_t i = 0; i < 500; i++) { + for (uint64_t i = 0; i < n; i++) { TEST_CHECK(vieter_heap_peek(&data, heap) == vieter_heap_ok); - TEST_CHECK(data == (void *)numbers[i]); + TEST_CHECK_(data == (void *)numbers[i], "peek %lx == %lx", (uint64_t)data, numbers[i]); data = NULL; TEST_CHECK(vieter_heap_pop(&data, heap) == vieter_heap_ok); - TEST_CHECK(data == (void *)numbers[i]); - TEST_SIZE(heap, (uint64_t)500 - i - 1); + TEST_CHECK_(data == (void *)numbers[i], "pop %lx == %lx", (uint64_t)data, numbers[i]); + TEST_SIZE(heap, n - i - 1); } vieter_heap_free(heap); @@ -125,8 +138,8 @@ void test_pop_random() { TEST_LIST = { {"init", test_init}, - {"merge same order", test_merge_same_order}, {"insert", test_insert}, + {"insert random", test_insert_random}, {"pop", test_pop}, {"pop random", test_pop_random}, {NULL, NULL} diff --git a/test/heap/test_merge.c b/test/heap/test_merge.c new file mode 100644 index 0000000..10053f2 --- /dev/null +++ b/test/heap/test_merge.c @@ -0,0 +1,28 @@ +#include "acutest.h" +#include "vieter_heap.h" +#include "vieter_heap_tree.h" +#include + +void test_merge_same_order() { + vieter_heap_node *root_a = vieter_heap_node_init(); + root_a->key = 1; + root_a->order = 0; + + vieter_heap_node *root_b = vieter_heap_node_init(); + root_b->key = 2; + root_b->order = 0; + + vieter_heap_node *merged = vieter_heap_tree_merge_same_order(root_a, root_b); + + TEST_CHECK(merged == root_a); + TEST_CHECK(merged->key == 1); + TEST_CHECK(merged->largest_order == root_b); + TEST_CHECK(merged->ptr.next_largest_order == NULL); + + vieter_heap_tree_free(merged); +} + +TEST_LIST = { + {"merge same order", test_merge_same_order}, + {NULL, NULL} +};