diff --git a/src/heap/vieter_heap_tree.h b/src/heap/vieter_heap_tree.h index b7597f6..c3bc55d 100644 --- a/src/heap/vieter_heap_tree.h +++ b/src/heap/vieter_heap_tree.h @@ -9,28 +9,45 @@ typedef struct vieter_heap_node { void *data; struct vieter_heap_node *largest_order; union { - struct vieter_heap_node *next_tree; - struct vieter_heap_node *next_largest_order; + // Roots point to next tree in the heap, other nodes point to their first + // neighbour. + struct vieter_heap_node *next_tree; + struct vieter_heap_node *next_largest_order; } ptr; uint8_t order; } vieter_heap_node; +/* + * Allocate an initialize a heap node object. + */ vieter_heap_node *vieter_heap_node_init(); +/* + * Deallocate a node object. + */ void vieter_heap_node_free(vieter_heap_node *node); -/* vieter_heap_tree *vieter_heap_tree_init(vieter_heap_node *root, vieter_heap_tree *next, uint8_t order); */ - /* - * Deallocate a tree object, along with its underlying tree structure. + * Deallocate a node's entire structure. */ void vieter_heap_tree_free(vieter_heap_node *root); +/* + * Given the roots of the smallest trees in two heaps, merge them into a single + * large heap. + */ vieter_heap_node *vieter_heap_tree_merge(vieter_heap_node *root_a, vieter_heap_node *root_b); +/* + * Given the roots of two trees of the same order, merge them into a heap of one + * order larger. + */ vieter_heap_node *vieter_heap_tree_merge_same_order(vieter_heap_node *root_a, vieter_heap_node *root_b); +/* + * Remove the smallest element from the given heap. + */ vieter_heap_node *vieter_heap_tree_pop(void **out, vieter_heap_node *root); #endif diff --git a/test/heap/test_heap.c b/test/heap/test_heap.c index 74736a3..e136d87 100644 --- a/test/heap/test_heap.c +++ b/test/heap/test_heap.c @@ -1,6 +1,7 @@ #include "acutest.h" #include "vieter_heap.h" #include "vieter_heap_tree.h" +#include #define TEST_SIZE(heap, size) \ TEST_CHECK(vieter_heap_size(heap) == size); \ @@ -76,10 +77,57 @@ void test_pop() { vieter_heap_free(heap); } +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)) { + return 1; + } else { + return 0; + } +} + +void test_pop_random() { + srand(0); + + vieter_heap *heap = vieter_heap_init(); + + uint64_t *numbers = malloc(500 * sizeof(uint64_t)); + uint64_t num; + + for (uint64_t i = 0; i < 500; i++) { + num = rand(); + vieter_heap_insert(heap, num, (void *)num); + TEST_SIZE(heap, i + 1); + + numbers[i] = num; + } + + + qsort(numbers, 500, sizeof(uint64_t), uint64_t_compare); + + void *data = NULL; + + for (uint64_t i = 0; i < 500; i++) { + TEST_CHECK(vieter_heap_peek(&data, heap) == vieter_heap_ok); + TEST_CHECK(data == (void *)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); + } + + vieter_heap_free(heap); + free(numbers); +} + TEST_LIST = { {"init", test_init}, {"merge same order", test_merge_same_order}, {"insert", test_insert}, {"pop", test_pop}, + {"pop random", test_pop_random}, {NULL, NULL} };