refactor(heap): some better variable names; some more tests
This commit is contained in:
parent
dc557f57ab
commit
3ec2e76af9
4 changed files with 83 additions and 54 deletions
|
|
@ -1,12 +1,7 @@
|
|||
#include "vieter_heap.h"
|
||||
#include "vieter_heap_tree.h"
|
||||
#include "vieter_heap_internal.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
struct vieter_heap {
|
||||
vieter_heap_node *tree;
|
||||
};
|
||||
|
||||
vieter_heap *vieter_heap_init() { return calloc(1, sizeof(vieter_heap)); }
|
||||
|
||||
uint64_t vieter_heap_size(vieter_heap *heap) {
|
||||
|
|
|
|||
6
src/heap/vieter_heap_internal.h
Normal file
6
src/heap/vieter_heap_internal.h
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
#include "vieter_heap.h"
|
||||
#include "vieter_heap_tree.h"
|
||||
|
||||
struct vieter_heap {
|
||||
vieter_heap_node *tree;
|
||||
};
|
||||
|
|
@ -43,90 +43,91 @@ end:
|
|||
|
||||
vieter_heap_node *vieter_heap_tree_merge_same_order(vieter_heap_node *root_a,
|
||||
vieter_heap_node *root_b) {
|
||||
vieter_heap_node *new_root;
|
||||
vieter_heap_node *root, *child;
|
||||
|
||||
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;
|
||||
root = root_a;
|
||||
child = root_b;
|
||||
} else {
|
||||
new_root = root_b;
|
||||
root_a->ptr.next_largest_order = root_b->largest_order;
|
||||
root_b->largest_order = root_a;
|
||||
root = root_b;
|
||||
child = root_a;
|
||||
}
|
||||
|
||||
new_root->order++;
|
||||
child->ptr.next_largest_order = root->largest_order;
|
||||
root->largest_order = child;
|
||||
|
||||
return new_root;
|
||||
root->order++;
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
vieter_heap_node *vieter_heap_tree_merge(vieter_heap_node *root_a,
|
||||
vieter_heap_node *root_b) {
|
||||
vieter_heap_node *root, *target, *out;
|
||||
vieter_heap_node *other_tree, *target_tree, *out;
|
||||
|
||||
if (root_a->order <= root_b->order) {
|
||||
target = root_a;
|
||||
root = root_b;
|
||||
target_tree = root_a;
|
||||
other_tree = root_b;
|
||||
} else {
|
||||
target = root_b;
|
||||
root = root_a;
|
||||
target_tree = root_b;
|
||||
other_tree = root_a;
|
||||
}
|
||||
|
||||
vieter_heap_node *next_tree, *next_target;
|
||||
vieter_heap_node *previous_target = NULL;
|
||||
vieter_heap_node *next_other_tree, *next_target_tree;
|
||||
vieter_heap_node *previous_target_tree = NULL;
|
||||
|
||||
while (target != NULL && root != NULL) {
|
||||
if (target->order == root->order) {
|
||||
next_tree = root->ptr.next_tree;
|
||||
next_target = target->ptr.next_tree;
|
||||
while (target_tree != NULL && other_tree != NULL) {
|
||||
if (target_tree->order == other_tree->order) {
|
||||
next_other_tree = other_tree->ptr.next_tree;
|
||||
next_target_tree = target_tree->ptr.next_tree;
|
||||
|
||||
target = vieter_heap_tree_merge_same_order(target, root);
|
||||
target_tree = vieter_heap_tree_merge_same_order(target_tree, other_tree);
|
||||
|
||||
target->ptr.next_tree = next_target;
|
||||
target_tree->ptr.next_tree = next_target_tree;
|
||||
|
||||
// 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->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;
|
||||
while (next_target_tree != NULL &&
|
||||
next_target_tree->order == target_tree->order) {
|
||||
next_target_tree = next_target_tree->ptr.next_tree;
|
||||
target_tree = vieter_heap_tree_merge_same_order(
|
||||
target_tree, target_tree->ptr.next_tree);
|
||||
target_tree->ptr.next_tree = next_target_tree;
|
||||
}
|
||||
|
||||
if (previous_target != NULL) {
|
||||
previous_target->ptr.next_tree = target;
|
||||
if (previous_target_tree != NULL) {
|
||||
previous_target_tree->ptr.next_tree = target_tree;
|
||||
} else {
|
||||
out = target;
|
||||
out = target_tree;
|
||||
}
|
||||
|
||||
root = next_tree;
|
||||
} else if (target->order > root->order) {
|
||||
next_tree = root->ptr.next_tree;
|
||||
other_tree = next_other_tree;
|
||||
} else if (target_tree->order > other_tree->order) {
|
||||
next_other_tree = other_tree->ptr.next_tree;
|
||||
|
||||
if (previous_target == NULL) {
|
||||
previous_target = root;
|
||||
out = root;
|
||||
if (previous_target_tree == NULL) {
|
||||
previous_target_tree = other_tree;
|
||||
out = other_tree;
|
||||
} else {
|
||||
previous_target->ptr.next_tree = root;
|
||||
previous_target_tree->ptr.next_tree = other_tree;
|
||||
}
|
||||
|
||||
root->ptr.next_tree = target;
|
||||
root = next_tree;
|
||||
other_tree->ptr.next_tree = target_tree;
|
||||
other_tree = next_other_tree;
|
||||
} else {
|
||||
if (previous_target == NULL) {
|
||||
out = target;
|
||||
if (previous_target_tree == NULL) {
|
||||
out = target_tree;
|
||||
}
|
||||
|
||||
previous_target = target;
|
||||
target = target->ptr.next_tree;
|
||||
previous_target_tree = target_tree;
|
||||
target_tree = target_tree->ptr.next_tree;
|
||||
}
|
||||
}
|
||||
|
||||
// Append final part of tree to target
|
||||
if (target == NULL) {
|
||||
previous_target->ptr.next_tree = root;
|
||||
if (target_tree == NULL) {
|
||||
previous_target_tree->ptr.next_tree = other_tree;
|
||||
}
|
||||
|
||||
return out;
|
||||
|
|
|
|||
Reference in a new issue