From 95d8c9972b4fb939546b03fc8b205186e146bf01 Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Tue, 24 Jan 2023 17:22:11 +0100 Subject: [PATCH] refactor(heap): combine tree and node into single struct --- src/heap/vieter_heap.c | 62 +++++------ src/heap/vieter_heap_tree.c | 212 ++++++++++++++++++------------------ src/heap/vieter_heap_tree.h | 24 ++-- test/heap/test_heap.c | 52 ++++----- 4 files changed, 171 insertions(+), 179 deletions(-) diff --git a/src/heap/vieter_heap.c b/src/heap/vieter_heap.c index dee109c..ae69805 100644 --- a/src/heap/vieter_heap.c +++ b/src/heap/vieter_heap.c @@ -4,30 +4,30 @@ #include struct vieter_heap { - vieter_heap_tree *tree; + vieter_heap_node *tree; }; vieter_heap *vieter_heap_init() { return calloc(1, sizeof(vieter_heap)); } uint64_t vieter_heap_size(vieter_heap *heap) { uint64_t size = 0; - vieter_heap_tree *tree = heap->tree; + vieter_heap_node *tree = heap->tree; while (tree != NULL) { size |= (uint64_t)1 << tree->order; - tree = tree->next; + tree = tree->ptr.next_tree; } return size; } void vieter_heap_free(vieter_heap *heap) { - vieter_heap_tree *tree = heap->tree; - vieter_heap_tree *next; + vieter_heap_node *tree = heap->tree; + vieter_heap_node *next; while (tree != NULL) { - next = tree->next; + next = tree->ptr.next_tree; vieter_heap_tree_free(tree); tree = next; } @@ -37,10 +37,10 @@ void vieter_heap_free(vieter_heap *heap) { vieter_heap_error vieter_heap_insert(vieter_heap *heap, uint64_t key, void *data) { - vieter_heap_node *new_node = vieter_heap_node_init(); - new_node->key = key; - new_node->data = data; - vieter_heap_tree *new_tree = vieter_heap_tree_init(new_node, NULL, 0); + vieter_heap_node *new_tree = vieter_heap_node_init(); + new_tree->key = key; + new_tree->data = data; + new_tree->order = 0; if (heap->tree == NULL) { heap->tree = new_tree; @@ -51,39 +51,39 @@ vieter_heap_error vieter_heap_insert(vieter_heap *heap, uint64_t key, return vieter_heap_ok; } -vieter_heap_error vieter_heap_pop(void **out, vieter_heap *heap) { - if (heap->tree == NULL) { - return vieter_heap_empty; - } +/* vieter_heap_error vieter_heap_pop(void **out, vieter_heap *heap) { */ +/* if (heap->tree == NULL) { */ +/* return vieter_heap_empty; */ +/* } */ - if (heap->tree->order == 0) { - *out = heap->tree->root->data; - vieter_heap_tree_free(heap->tree); - heap->tree = NULL; +/* if (heap->tree->order == 0) { */ +/* *out = heap->tree->root->data; */ +/* vieter_heap_tree_free(heap->tree); */ +/* heap->tree = NULL; */ - return vieter_heap_ok; - } +/* return vieter_heap_ok; */ +/* } */ - vieter_heap_tree_pop(out, heap->tree); +/* vieter_heap_tree_pop(out, heap->tree); */ - return vieter_heap_ok; -} +/* return vieter_heap_ok; */ +/* } */ vieter_heap_error vieter_heap_peek(void **out, vieter_heap *heap) { if (heap->tree == NULL) { return vieter_heap_empty; } - vieter_heap_tree *tree = heap->tree; - uint64_t smallest_key = tree->root->key; - *out = tree->root->data; + vieter_heap_node *tree = heap->tree; + uint64_t smallest_key = tree->key; + *out = tree->data; - while (tree->next != NULL) { - tree = tree->next; + while (tree->ptr.next_tree != NULL) { + tree = tree->ptr.next_tree; - if (tree->root->key < smallest_key) { - smallest_key = tree->root->key; - *out = tree->root->data; + if (tree->key < smallest_key) { + smallest_key = tree->key; + *out = tree->data; } } diff --git a/src/heap/vieter_heap_tree.c b/src/heap/vieter_heap_tree.c index 9a170e3..584ab46 100644 --- a/src/heap/vieter_heap_tree.c +++ b/src/heap/vieter_heap_tree.c @@ -6,11 +6,15 @@ vieter_heap_node *vieter_heap_node_init() { void vieter_heap_node_free(vieter_heap_node *node) { free(node); } -void vieter_heap_tree_free(vieter_heap_tree *tree) { +void vieter_heap_tree_free(vieter_heap_node *root) { + if (root->order == 0) { + goto end; + } + uint64_t size = 1; vieter_heap_node **stack = - malloc(((uint64_t)1 << tree->order) * sizeof(vieter_heap_node *)); - stack[0] = tree->root; + malloc(((uint64_t)1 << root->order) * sizeof(vieter_heap_node *)); + stack[0] = root->largest_order; vieter_heap_node *node; @@ -23,8 +27,8 @@ void vieter_heap_tree_free(vieter_heap_tree *tree) { size++; } - if (node->next_largest_order != NULL) { - stack[size] = node->next_largest_order; + if (node->ptr.next_largest_order != NULL) { + stack[size] = node->ptr.next_largest_order; size++; } @@ -32,170 +36,160 @@ void vieter_heap_tree_free(vieter_heap_tree *tree) { } free(stack); - free(tree); + +end: + vieter_heap_node_free(root); } -vieter_heap_tree *vieter_heap_tree_init(vieter_heap_node *root, - vieter_heap_tree *next, uint8_t order) { - vieter_heap_tree *tree = malloc(sizeof(vieter_heap_tree)); +/* vieter_heap_tree *vieter_heap_tree_init(vieter_heap_node *root, */ +/* vieter_heap_tree *next, uint8_t + * order) { */ +/* vieter_heap_tree *tree = malloc(sizeof(vieter_heap_tree)); */ - tree->root = root; - tree->next = next; - tree->order = order; +/* tree->root = root; */ +/* tree->next = next; */ +/* tree->order = order; */ - return tree; -} +/* return tree; */ +/* } */ -void vieter_heap_tree_swap(vieter_heap_tree *t1, vieter_heap_tree *t2) { - vieter_heap_tree temp = { - .order = t1->order, .root = t1->root, .next = t1->next}; +vieter_heap_node *vieter_heap_tree_merge_same_order(vieter_heap_node *root_a, + vieter_heap_node *root_b) { + vieter_heap_node *new_root; - t1->order = t2->order; - t1->root = t2->root; - t1->next = t2->next; - - t2->order = temp.order; - t2->root = temp.root; - t2->next = temp.next; -} - -vieter_heap_tree *vieter_heap_tree_merge_same_order(vieter_heap_tree *tree_a, - vieter_heap_tree *tree_b) { - vieter_heap_tree *new_tree; - - if (tree_a->root->key <= tree_b->root->key) { - new_tree = tree_a; - tree_a->root->next_largest_order = tree_a->root->largest_order; - tree_a->root->largest_order = tree_b->root; - - free(tree_b); + if (root_a->key <= root_b->key) { + new_root = root_a; + root_b->ptr.next_largest_order = root_a->largest_order; + root_a->largest_order = root_b; } else { - new_tree = tree_b; - tree_b->root->next_largest_order = tree_b->root->largest_order; - tree_b->root->largest_order = tree_a->root; - - free(tree_a); + new_root = root_b; + root_a->ptr.next_largest_order = root_b->largest_order; + root_b->largest_order = root_a; } - new_tree->order++; + new_root->order++; - return new_tree; + return new_root; } -vieter_heap_tree *vieter_heap_tree_merge(vieter_heap_tree *tree_a, - vieter_heap_tree *tree_b) { - vieter_heap_tree *tree, *target, *out; +vieter_heap_node *vieter_heap_tree_merge(vieter_heap_node *root_a, + vieter_heap_node *root_b) { + vieter_heap_node *root, *target, *out; - if (tree_a->order <= tree_b->order) { - target = tree_a; - tree = tree_b; + if (root_a->order <= root_b->order) { + target = root_a; + root = root_b; } else { - target = tree_b; - tree = tree_a; + target = root_b; + root = root_a; } - vieter_heap_tree *next_tree, *next_target; - vieter_heap_tree *previous_target = NULL; + vieter_heap_node *next_tree, *next_target; + vieter_heap_node *previous_target = NULL; - while (target != NULL && tree != NULL) { - if (target->order == tree->order) { - next_tree = tree->next; - next_target = target->next; + while (target != NULL && root != NULL) { + if (target->order == root->order) { + next_tree = root->ptr.next_tree; + next_target = target->ptr.next_tree; - target = vieter_heap_tree_merge_same_order(target, tree); + target = vieter_heap_tree_merge_same_order(target, root); - target->next = next_target; + target->ptr.next_tree = next_target; // If this merge produces a binomial tree whose size is already in // target, it will be the next target. Therefore, we can merge target's // trees until we no longer have a duplicate depth. - while (target->next != NULL && target->next->order == target->order) { - next_target = target->next->next; - target = vieter_heap_tree_merge_same_order(target, target->next); - target->next = next_target; + while (target->ptr.next_tree != NULL && + target->ptr.next_tree->order == target->order) { + next_target = target->ptr.next_tree->ptr.next_tree; + target = + vieter_heap_tree_merge_same_order(target, target->ptr.next_tree); + target->ptr.next_tree = next_target; } if (previous_target != NULL) { - previous_target->next = target; + previous_target->ptr.next_tree = target; } else { out = target; } - tree = next_tree; - } else if (target->order > tree->order) { - next_tree = tree->next; + root = next_tree; + } else if (target->order > root->order) { + next_tree = root->ptr.next_tree; if (previous_target == NULL) { - previous_target = tree; - out = tree; + previous_target = root; + out = root; } else { - previous_target->next = tree; + previous_target->ptr.next_tree = root; } - tree->next = target; - tree = next_tree; + root->ptr.next_tree = target; + root = next_tree; } else { if (previous_target == NULL) { out = target; } previous_target = target; - target = target->next; + target = target->ptr.next_tree; } } // Append final part of tree to target if (target == NULL) { - previous_target->next = tree; + previous_target->ptr.next_tree = root; } return out; } -vieter_heap_tree *vieter_heap_tree_pop(void **out, vieter_heap_tree *tree) { - vieter_heap_tree *tree_before_smallest = NULL; - vieter_heap_tree *previous_tree = NULL; - vieter_heap_tree *tree_out = tree; +/* vieter_heap_tree *vieter_heap_tree_pop(void **out, vieter_heap_tree *tree) { + */ +/* vieter_heap_tree *tree_before_smallest = NULL; */ +/* vieter_heap_tree *previous_tree = NULL; */ +/* vieter_heap_tree *tree_out = tree; */ - uint64_t smallest_key = tree->root->key; +/* uint64_t smallest_key = tree->root->key; */ - while (tree->next != NULL) { - previous_tree = tree; - tree = tree->next; +/* while (tree->next != NULL) { */ +/* previous_tree = tree; */ +/* tree = tree->next; */ - if (tree->root->key < smallest_key) { - smallest_key = tree->root->key; - *out = tree->root->data; - tree_before_smallest = previous_tree; - } - } +/* if (tree->root->key < smallest_key) { */ +/* smallest_key = tree->root->key; */ +/* *out = tree->root->data; */ +/* tree_before_smallest = previous_tree; */ +/* } */ +/* } */ - if (tree_before_smallest != NULL) { - previous_tree->next = tree->next; - } else { - tree_out = tree_out->next; - } +/* if (tree_before_smallest != NULL) { */ +/* previous_tree->next = tree->next; */ +/* } else { */ +/* tree_out = tree_out->next; */ +/* } */ - if (tree->order == 0) { - vieter_heap_tree_free(tree); +/* if (tree->order == 0) { */ +/* vieter_heap_tree_free(tree); */ - return NULL; - } +/* return NULL; */ +/* } */ - uint8_t old_order = tree->order; +/* uint8_t old_order = tree->order; */ - vieter_heap_node *node = tree->root->largest_order; - free(tree->root); +/* vieter_heap_node *node = tree->root->largest_order; */ +/* free(tree->root); */ - previous_tree = vieter_heap_tree_init(node, NULL, old_order - 1); +/* previous_tree = vieter_heap_tree_init(node, NULL, old_order - 1); */ - uint8_t i = 2; - while (node->next_largest_order != NULL) { - node = node->next_largest_order; - previous_tree = vieter_heap_tree_init(node, previous_tree, old_order - i); +/* uint8_t i = 2; */ +/* while (node->next_largest_order != NULL) { */ +/* node = node->next_largest_order; */ +/* previous_tree = vieter_heap_tree_init(node, previous_tree, old_order - + * i); */ - i++; - } +/* i++; */ +/* } */ - return vieter_heap_tree_merge(tree_out, previous_tree); -} +/* return vieter_heap_tree_merge(tree_out, previous_tree); */ +/* } */ diff --git a/src/heap/vieter_heap_tree.h b/src/heap/vieter_heap_tree.h index 10c6256..b7597f6 100644 --- a/src/heap/vieter_heap_tree.h +++ b/src/heap/vieter_heap_tree.h @@ -8,31 +8,29 @@ typedef struct vieter_heap_node { uint64_t key; void *data; struct vieter_heap_node *largest_order; - struct vieter_heap_node *next_largest_order; + union { + struct vieter_heap_node *next_tree; + struct vieter_heap_node *next_largest_order; + } ptr; + uint8_t order; } vieter_heap_node; vieter_heap_node *vieter_heap_node_init(); void vieter_heap_node_free(vieter_heap_node *node); -typedef struct vieter_heap_tree { - uint8_t order; - vieter_heap_node *root; - struct vieter_heap_tree *next; -} vieter_heap_tree; - -vieter_heap_tree *vieter_heap_tree_init(vieter_heap_node *root, vieter_heap_tree *next, uint8_t order); +/* 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. */ -void vieter_heap_tree_free(vieter_heap_tree *tree); +void vieter_heap_tree_free(vieter_heap_node *root); -vieter_heap_tree *vieter_heap_tree_merge(vieter_heap_tree *tree_a, vieter_heap_tree *tree_b); +vieter_heap_node *vieter_heap_tree_merge(vieter_heap_node *root_a, vieter_heap_node *root_b); -vieter_heap_tree *vieter_heap_tree_merge_same_order(vieter_heap_tree *tree_a, - vieter_heap_tree *tree_b); +vieter_heap_node *vieter_heap_tree_merge_same_order(vieter_heap_node *root_a, + vieter_heap_node *root_b); -vieter_heap_tree *vieter_heap_tree_pop(void **out, vieter_heap_tree *tree); +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 dbc26b8..f795ebe 100644 --- a/test/heap/test_heap.c +++ b/test/heap/test_heap.c @@ -16,18 +16,18 @@ void test_init() { void test_merge_same_order() { vieter_heap_node *root_a = vieter_heap_node_init(); root_a->key = 1; - vieter_heap_tree *tree_a = vieter_heap_tree_init(root_a, NULL, 1); + root_a->order = 0; vieter_heap_node *root_b = vieter_heap_node_init(); root_b->key = 2; - vieter_heap_tree *tree_b = vieter_heap_tree_init(root_b, NULL, 1); + root_b->order = 0; - vieter_heap_tree *merged = vieter_heap_tree_merge_same_order(tree_a, tree_b); + vieter_heap_node *merged = vieter_heap_tree_merge_same_order(root_a, root_b); - TEST_CHECK(merged == tree_a); - TEST_CHECK(merged->root->key == 1); - TEST_CHECK(merged->root->largest_order == root_b); - TEST_CHECK(merged->root->next_largest_order == NULL); + 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); } @@ -51,35 +51,35 @@ void test_insert() { vieter_heap_free(heap); } -void test_pop() { - vieter_heap *heap = vieter_heap_init(); - TEST_SIZE(heap, 0); +/* void test_pop() { */ +/* vieter_heap *heap = vieter_heap_init(); */ +/* TEST_SIZE(heap, 0); */ - void *data; +/* void *data; */ - for (uint64_t i = 50; i > 0; i--) { - vieter_heap_insert(heap, i, (void *)i); - TEST_SIZE(heap, (uint64_t)51 - i); +/* for (uint64_t i = 50; i > 0; i--) { */ +/* vieter_heap_insert(heap, i, (void *)i); */ +/* TEST_SIZE(heap, (uint64_t)51 - i); */ - TEST_CHECK(vieter_heap_peek(&data, heap) == vieter_heap_ok); - TEST_CHECK(data == (void*)i); - } +/* TEST_CHECK(vieter_heap_peek(&data, heap) == vieter_heap_ok); */ +/* TEST_CHECK(data == (void*)i); */ +/* } */ - data = NULL; +/* data = NULL; */ - for (uint64_t i = 1; i <= 50; i++) { - TEST_CHECK(vieter_heap_pop(&data, heap) == vieter_heap_ok); - TEST_CHECK(data == (void*)i); - TEST_SIZE(heap, (uint64_t)50 - i); - } +/* for (uint64_t i = 1; i <= 50; i++) { */ +/* TEST_CHECK(vieter_heap_pop(&data, heap) == vieter_heap_ok); */ +/* TEST_CHECK(data == (void*)i); */ +/* TEST_SIZE(heap, (uint64_t)50 - i); */ +/* } */ - vieter_heap_free(heap); -} +/* vieter_heap_free(heap); */ +/* } */ TEST_LIST = { {"init", test_init}, {"merge same order", test_merge_same_order}, {"insert", test_insert}, - {"pop", test_pop}, + /* {"pop", test_pop}, */ {NULL, NULL} };