libvieter/src/heap/vieter_heap_tree.c

114 lines
2.9 KiB
C

#include "vieter_heap_tree.h"
vieter_heap_node *vieter_heap_node_init() {
return calloc(1, sizeof(vieter_heap_node));
}
vieter_heap_tree *vieter_heap_tree_init(vieter_heap_node *root,
vieter_heap_tree *next,
uint64_t order) {
vieter_heap_tree *tree = malloc(sizeof(vieter_heap_tree));
tree->root = root;
tree->next = next;
tree->order = order;
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};
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);
} 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_tree->order++;
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;
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;
} else {
previous_target = target;
target = target->next;
}
}
// Append final part of tree to target
target->next = tree;
return target;
}