diff --git a/Makefile b/Makefile index 5795f7c..4a26c17 100644 --- a/Makefile +++ b/Makefile @@ -25,7 +25,7 @@ INC_FLAGS := $(addprefix -I,$(INC_DIRS)) # object file is also recompiled if only a header is changed. # -MP: generate a dummy target for every header file (according to the docs it # prevents some errors when removing header files) -CFLAGS ?= -MMD -MP -g +CFLAGS ?= -MMD -MP VIETERCFLAGS := $(INC_FLAGS) $(CFLAGS) -Wall -Wextra .PHONY: all diff --git a/src/heap/vieter_heap.c b/src/heap/vieter_heap.c index ceecdbb..6d543df 100644 --- a/src/heap/vieter_heap.c +++ b/src/heap/vieter_heap.c @@ -9,18 +9,7 @@ struct vieter_heap { 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; - - while (tree != NULL) { - size |= 1 << tree->order; - - tree = tree->next; - } - - return size; -} +uint64_t vieter_heap_size(vieter_heap *heap) { return 0; } void vieter_heap_free(vieter_heap *heap) {} @@ -45,22 +34,5 @@ vieter_heap_error vieter_heap_pop(void **out, vieter_heap *heap) { } vieter_heap_error vieter_heap_peek(void **out, vieter_heap *heap) { - if (heap->tree == NULL) { - return vieter_heap_empty; - } - - uint64_t smallest_key; - - vieter_heap_tree *tree = heap->tree; - - while (tree != NULL) { - if (tree->root->key < smallest_key) { - smallest_key = tree->root->key; - *out = tree->root->data; - } - - tree = tree->next; - } - return vieter_heap_ok; } diff --git a/src/heap/vieter_heap_tree.c b/src/heap/vieter_heap_tree.c index b3e3d1e..75b38d2 100644 --- a/src/heap/vieter_heap_tree.c +++ b/src/heap/vieter_heap_tree.c @@ -17,16 +17,19 @@ vieter_heap_tree *vieter_heap_tree_init(vieter_heap_node *root, } 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_tree temp = { + .order = t1->order, + .root = t1->root, + .next = t1->next + }; - t1->order = t2->order; - t1->root = t2->root; - t1->next = t2->next; + t1->order = t2->order; + t1->root = t2->root; + t1->next = t2->next; - t2->order = temp.order; - t2->root = temp.root; - t2->next = temp.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, @@ -34,13 +37,13 @@ vieter_heap_tree *vieter_heap_tree_merge_same_order(vieter_heap_tree *tree_a, vieter_heap_tree *new_tree; if (tree_a->root->key <= tree_b->root->key) { - new_tree = tree_a; + 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); } else { - new_tree = tree_b; + new_tree = tree_b; tree_b->root->next_largest_order = tree_b->root->largest_order; tree_b->root->largest_order = tree_a->root; @@ -52,62 +55,54 @@ vieter_heap_tree *vieter_heap_tree_merge_same_order(vieter_heap_tree *tree_a, return new_tree; } -vieter_heap_tree *vieter_heap_tree_merge(vieter_heap_tree *tree_a, - vieter_heap_tree *tree_b) { - vieter_heap_tree *tree, *target; +vieter_heap_tree *vieter_heap_tree_merge(vieter_heap_tree *tree_a, vieter_heap_tree *tree_b) { + vieter_heap_tree *tree, *target; - if (tree_a->order <= tree_b->order) { - target = tree_a; - tree = tree_b; - } else { - target = tree_b; - tree = tree_a; - } - - vieter_heap_tree *next_tree, *next_target; - vieter_heap_tree *previous_target = NULL; - - while (target != NULL && target != NULL) { - if (target->order == tree->order) { - next_tree = tree->next; - next_target = target->next; - - target = vieter_heap_tree_merge_same_order(target, tree); - - target->next = next_target; - - if (previous_target != NULL) { - previous_target->next = target; - } - - tree = next_tree; - - // If this merge produces a binomial tree whose size is already in - // target, it will be the next target. Therefore, we can target's - // trees until we no longer have a duplicate depth. - while (target->next != NULL && target->next->order == target->order) { - next_target = target->next; - target = vieter_heap_tree_merge_same_order(target, target->next); - target->next = next_target; - } - } else if (target->order > tree->order) { - if (previous_target == NULL) { - previous_target = tree; - } else { - previous_target->next = tree; - } - - tree->next = target; - - tree = tree->next; + if (tree_a->order <= tree_b->order) { + target = tree_a; + tree = tree_b; } else { - previous_target = target; - target = target->next; + target = tree_b; + tree = tree_a; } - } - // Append final part of tree to target - target->next = tree; + vieter_heap_tree *next_tree, *next_target; + vieter_heap_tree *previous_target = target; - return target; + while (1) { + if (target->order == tree->order) { + next_tree = tree->next; + next_target = target->next; + + target = vieter_heap_tree_merge_same_order(target, tree); + + // TODO what when this merge produces an order that's already in target + + target->next = next_target; + previous_target->next = target; + + tree = next_tree; + } else if (target->order > tree->order) { + previous_target->next = tree; + tree->next = target; + + tree = tree->next; + } else { + previous_target = target; + target = target->next; + } + } + + if (target->order > tree->order) { + vieter_heap_tree_swap(target, tree); + + } else if (target->order == tree->order) { + target->root->next_largest_order = target->root->largest_order; + target->root->largest_order = tree->root; + target->order++; + + next_tree = tree->next; + free(tree); + tree = next_tree; + } } diff --git a/test/heap/test_heap.c b/test/heap/test_heap.c index 7367f28..832404d 100644 --- a/test/heap/test_heap.c +++ b/test/heap/test_heap.c @@ -13,41 +13,7 @@ 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; - vieter_heap_tree *tree_a = vieter_heap_tree_init(root_a, NULL, 1); - - 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); - - vieter_heap_tree *merged = vieter_heap_tree_merge_same_order(tree_a, tree_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); -} - -void test_insert() { - vieter_heap *heap = vieter_heap_init(); - TEST_SIZE(heap, 0); - - void *data; - - 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_LIST = { {"test_init", test_init}, - {"test_merge_same_order", test_merge_same_order}, - {"test_insert", test_insert}, {NULL, NULL} };