2023-01-22 09:40:35 +01:00
|
|
|
#include "vieter_heap_tree.h"
|
|
|
|
|
|
|
|
vieter_heap_node *vieter_heap_node_init() {
|
|
|
|
return calloc(1, sizeof(vieter_heap_node));
|
|
|
|
}
|
|
|
|
|
2023-01-24 12:07:30 +01:00
|
|
|
void vieter_heap_node_free(vieter_heap_node *node) { free(node); }
|
|
|
|
|
2023-01-24 17:22:11 +01:00
|
|
|
void vieter_heap_tree_free(vieter_heap_node *root) {
|
|
|
|
if (root->order == 0) {
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
2023-01-24 12:07:30 +01:00
|
|
|
uint64_t size = 1;
|
|
|
|
vieter_heap_node **stack =
|
2023-01-24 17:22:11 +01:00
|
|
|
malloc(((uint64_t)1 << root->order) * sizeof(vieter_heap_node *));
|
|
|
|
stack[0] = root->largest_order;
|
2023-01-24 12:07:30 +01:00
|
|
|
|
|
|
|
vieter_heap_node *node;
|
|
|
|
|
|
|
|
while (size > 0) {
|
|
|
|
node = stack[size - 1];
|
|
|
|
size--;
|
|
|
|
|
|
|
|
if (node->largest_order != NULL) {
|
|
|
|
stack[size] = node->largest_order;
|
|
|
|
size++;
|
|
|
|
}
|
|
|
|
|
2023-01-24 17:22:11 +01:00
|
|
|
if (node->ptr.next_largest_order != NULL) {
|
|
|
|
stack[size] = node->ptr.next_largest_order;
|
2023-01-24 12:07:30 +01:00
|
|
|
size++;
|
|
|
|
}
|
|
|
|
|
|
|
|
vieter_heap_node_free(node);
|
|
|
|
}
|
|
|
|
|
|
|
|
free(stack);
|
2023-01-22 09:40:35 +01:00
|
|
|
|
2023-01-24 17:22:11 +01:00
|
|
|
end:
|
|
|
|
vieter_heap_node_free(root);
|
2023-01-22 09:40:35 +01:00
|
|
|
}
|
|
|
|
|
2023-01-24 17:22:11 +01:00
|
|
|
vieter_heap_node *vieter_heap_tree_merge_same_order(vieter_heap_node *root_a,
|
|
|
|
vieter_heap_node *root_b) {
|
|
|
|
vieter_heap_node *new_root;
|
2023-01-22 20:34:05 +01:00
|
|
|
|
2023-01-24 17:22:11 +01:00
|
|
|
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;
|
2023-01-22 20:34:05 +01:00
|
|
|
} else {
|
2023-01-24 17:22:11 +01:00
|
|
|
new_root = root_b;
|
|
|
|
root_a->ptr.next_largest_order = root_b->largest_order;
|
|
|
|
root_b->largest_order = root_a;
|
2023-01-22 20:34:05 +01:00
|
|
|
}
|
|
|
|
|
2023-01-24 17:22:11 +01:00
|
|
|
new_root->order++;
|
2023-01-22 20:34:05 +01:00
|
|
|
|
2023-01-24 17:22:11 +01:00
|
|
|
return new_root;
|
2023-01-22 20:34:05 +01:00
|
|
|
}
|
|
|
|
|
2023-01-24 17:22:11 +01:00
|
|
|
vieter_heap_node *vieter_heap_tree_merge(vieter_heap_node *root_a,
|
|
|
|
vieter_heap_node *root_b) {
|
|
|
|
vieter_heap_node *root, *target, *out;
|
2023-01-22 20:34:05 +01:00
|
|
|
|
2023-01-24 17:22:11 +01:00
|
|
|
if (root_a->order <= root_b->order) {
|
|
|
|
target = root_a;
|
|
|
|
root = root_b;
|
2023-01-22 20:34:05 +01:00
|
|
|
} else {
|
2023-01-24 17:22:11 +01:00
|
|
|
target = root_b;
|
|
|
|
root = root_a;
|
2023-01-22 20:34:05 +01:00
|
|
|
}
|
|
|
|
|
2023-01-24 17:22:11 +01:00
|
|
|
vieter_heap_node *next_tree, *next_target;
|
|
|
|
vieter_heap_node *previous_target = NULL;
|
2023-01-22 20:34:05 +01:00
|
|
|
|
2023-01-24 17:22:11 +01:00
|
|
|
while (target != NULL && root != NULL) {
|
|
|
|
if (target->order == root->order) {
|
|
|
|
next_tree = root->ptr.next_tree;
|
|
|
|
next_target = target->ptr.next_tree;
|
2023-01-22 20:34:05 +01:00
|
|
|
|
2023-01-24 17:22:11 +01:00
|
|
|
target = vieter_heap_tree_merge_same_order(target, root);
|
2023-01-22 20:34:05 +01:00
|
|
|
|
2023-01-24 17:22:11 +01:00
|
|
|
target->ptr.next_tree = next_target;
|
2023-01-22 20:34:05 +01:00
|
|
|
|
|
|
|
// If this merge produces a binomial tree whose size is already in
|
2023-01-24 12:07:30 +01:00
|
|
|
// target, it will be the next target. Therefore, we can merge target's
|
2023-01-22 20:34:05 +01:00
|
|
|
// trees until we no longer have a duplicate depth.
|
2023-01-24 17:22:11 +01:00
|
|
|
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;
|
2023-01-22 20:34:05 +01:00
|
|
|
}
|
2023-01-24 12:07:30 +01:00
|
|
|
|
|
|
|
if (previous_target != NULL) {
|
2023-01-24 17:22:11 +01:00
|
|
|
previous_target->ptr.next_tree = target;
|
2023-01-24 12:07:30 +01:00
|
|
|
} else {
|
|
|
|
out = target;
|
|
|
|
}
|
|
|
|
|
2023-01-24 17:22:11 +01:00
|
|
|
root = next_tree;
|
|
|
|
} else if (target->order > root->order) {
|
|
|
|
next_tree = root->ptr.next_tree;
|
2023-01-24 12:07:30 +01:00
|
|
|
|
2023-01-22 20:34:05 +01:00
|
|
|
if (previous_target == NULL) {
|
2023-01-24 17:22:11 +01:00
|
|
|
previous_target = root;
|
|
|
|
out = root;
|
2023-01-22 20:34:05 +01:00
|
|
|
} else {
|
2023-01-24 17:22:11 +01:00
|
|
|
previous_target->ptr.next_tree = root;
|
2023-01-22 20:34:05 +01:00
|
|
|
}
|
|
|
|
|
2023-01-24 17:22:11 +01:00
|
|
|
root->ptr.next_tree = target;
|
|
|
|
root = next_tree;
|
2023-01-22 20:34:05 +01:00
|
|
|
} else {
|
2023-01-24 12:07:30 +01:00
|
|
|
if (previous_target == NULL) {
|
|
|
|
out = target;
|
|
|
|
}
|
|
|
|
|
2023-01-22 20:34:05 +01:00
|
|
|
previous_target = target;
|
2023-01-24 17:22:11 +01:00
|
|
|
target = target->ptr.next_tree;
|
2023-01-22 20:34:05 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Append final part of tree to target
|
2023-01-24 12:07:30 +01:00
|
|
|
if (target == NULL) {
|
2023-01-24 17:22:11 +01:00
|
|
|
previous_target->ptr.next_tree = root;
|
2023-01-24 12:07:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
2023-01-24 19:45:01 +01:00
|
|
|
vieter_heap_node *vieter_heap_tree_pop(void **out, vieter_heap_node *tree) {
|
|
|
|
vieter_heap_node *tree_before_smallest = NULL;
|
|
|
|
vieter_heap_node *previous_tree = NULL;
|
|
|
|
vieter_heap_node *original_root = tree;
|
|
|
|
|
|
|
|
uint64_t smallest_key = tree->key;
|
2023-01-24 17:01:37 +01:00
|
|
|
|
2023-01-24 19:45:01 +01:00
|
|
|
while (tree->ptr.next_tree != NULL) {
|
|
|
|
previous_tree = tree;
|
|
|
|
tree = tree->ptr.next_tree;
|
|
|
|
|
|
|
|
if (tree->key < smallest_key) {
|
|
|
|
smallest_key = tree->key;
|
|
|
|
tree_before_smallest = previous_tree;
|
|
|
|
}
|
|
|
|
}
|
2023-01-24 17:01:37 +01:00
|
|
|
|
2023-01-24 19:45:01 +01:00
|
|
|
vieter_heap_node *tree_to_pop;
|
2023-01-24 17:01:37 +01:00
|
|
|
|
2023-01-24 19:45:01 +01:00
|
|
|
if (tree_before_smallest != NULL) {
|
|
|
|
tree_to_pop = tree_before_smallest->ptr.next_tree;
|
|
|
|
tree_before_smallest->ptr.next_tree = tree_to_pop->ptr.next_tree;
|
|
|
|
} else {
|
|
|
|
tree_to_pop = original_root;
|
|
|
|
original_root = original_root->ptr.next_tree;
|
|
|
|
}
|
2023-01-24 17:01:37 +01:00
|
|
|
|
2023-01-24 19:45:01 +01:00
|
|
|
*out = tree_to_pop->data;
|
2023-01-24 17:01:37 +01:00
|
|
|
|
2023-01-24 19:45:01 +01:00
|
|
|
if (tree_to_pop->order == 0) {
|
|
|
|
vieter_heap_tree_free(tree_to_pop);
|
2023-01-24 17:01:37 +01:00
|
|
|
|
2023-01-24 19:45:01 +01:00
|
|
|
return original_root;
|
|
|
|
}
|
2023-01-24 17:01:37 +01:00
|
|
|
|
2023-01-24 19:45:01 +01:00
|
|
|
previous_tree = tree_to_pop->largest_order;
|
|
|
|
vieter_heap_node_free(tree_to_pop);
|
2023-01-24 17:01:37 +01:00
|
|
|
|
2023-01-24 19:45:01 +01:00
|
|
|
tree = previous_tree->ptr.next_largest_order;
|
|
|
|
previous_tree->ptr.next_tree = NULL;
|
2023-01-24 17:01:37 +01:00
|
|
|
|
2023-01-24 19:45:01 +01:00
|
|
|
vieter_heap_node *next_tree;
|
2023-01-24 17:01:37 +01:00
|
|
|
|
2023-01-24 19:45:01 +01:00
|
|
|
while (tree != NULL) {
|
|
|
|
next_tree = tree->ptr.next_largest_order;
|
|
|
|
tree->ptr.next_tree = previous_tree;
|
2023-01-24 17:01:37 +01:00
|
|
|
|
2023-01-24 19:45:01 +01:00
|
|
|
previous_tree = tree;
|
|
|
|
tree = next_tree;
|
|
|
|
}
|
2023-01-22 20:34:05 +01:00
|
|
|
|
2023-01-24 19:45:01 +01:00
|
|
|
// original_root is zero if the heap only contained a single tree.
|
|
|
|
if (original_root != NULL) {
|
|
|
|
return vieter_heap_tree_merge(original_root, previous_tree);
|
|
|
|
} else {
|
|
|
|
return previous_tree;
|
|
|
|
}
|
|
|
|
}
|