fix(heap): some insert fixes
This commit is contained in:
parent
c1ad26cf0c
commit
3c8c33b47a
4 changed files with 135 additions and 30 deletions
|
|
@ -14,7 +14,7 @@ uint64_t vieter_heap_size(vieter_heap *heap) {
|
|||
vieter_heap_tree *tree = heap->tree;
|
||||
|
||||
while (tree != NULL) {
|
||||
size |= 1 << tree->order;
|
||||
size |= (uint64_t)1 << tree->order;
|
||||
|
||||
tree = tree->next;
|
||||
}
|
||||
|
|
@ -22,14 +22,25 @@ uint64_t vieter_heap_size(vieter_heap *heap) {
|
|||
return size;
|
||||
}
|
||||
|
||||
void vieter_heap_free(vieter_heap *heap) {}
|
||||
void vieter_heap_free(vieter_heap *heap) {
|
||||
vieter_heap_tree *tree = heap->tree;
|
||||
vieter_heap_tree *next;
|
||||
|
||||
while (tree != NULL) {
|
||||
next = tree->next;
|
||||
vieter_heap_tree_free(tree);
|
||||
tree = next;
|
||||
}
|
||||
|
||||
free(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, 1);
|
||||
vieter_heap_tree *new_tree = vieter_heap_tree_init(new_node, NULL, 0);
|
||||
|
||||
if (heap->tree == NULL) {
|
||||
heap->tree = new_tree;
|
||||
|
|
@ -41,6 +52,18 @@ vieter_heap_error vieter_heap_insert(vieter_heap *heap, uint64_t key,
|
|||
}
|
||||
|
||||
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;
|
||||
|
||||
return vieter_heap_ok;
|
||||
}
|
||||
|
||||
return vieter_heap_ok;
|
||||
}
|
||||
|
||||
|
|
@ -49,17 +72,17 @@ vieter_heap_error vieter_heap_peek(void **out, vieter_heap *heap) {
|
|||
return vieter_heap_empty;
|
||||
}
|
||||
|
||||
uint64_t smallest_key;
|
||||
|
||||
vieter_heap_tree *tree = heap->tree;
|
||||
uint64_t smallest_key = tree->root->key;
|
||||
*out = tree->root->data;
|
||||
|
||||
while (tree->next != NULL) {
|
||||
tree = tree->next;
|
||||
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -4,9 +4,39 @@ vieter_heap_node *vieter_heap_node_init() {
|
|||
return calloc(1, sizeof(vieter_heap_node));
|
||||
}
|
||||
|
||||
void vieter_heap_node_free(vieter_heap_node *node) { free(node); }
|
||||
|
||||
void vieter_heap_tree_free(vieter_heap_tree *tree) {
|
||||
uint64_t size = 1;
|
||||
vieter_heap_node **stack =
|
||||
malloc(((uint64_t)1 << tree->order) * sizeof(vieter_heap_node *));
|
||||
stack[0] = tree->root;
|
||||
|
||||
vieter_heap_node *node;
|
||||
|
||||
while (size > 0) {
|
||||
node = stack[size - 1];
|
||||
size--;
|
||||
|
||||
if (node->largest_order != NULL) {
|
||||
stack[size] = node->largest_order;
|
||||
size++;
|
||||
}
|
||||
|
||||
if (node->next_largest_order != NULL) {
|
||||
stack[size] = node->next_largest_order;
|
||||
size++;
|
||||
}
|
||||
|
||||
vieter_heap_node_free(node);
|
||||
}
|
||||
|
||||
free(stack);
|
||||
free(tree);
|
||||
}
|
||||
|
||||
vieter_heap_tree *vieter_heap_tree_init(vieter_heap_node *root,
|
||||
vieter_heap_tree *next,
|
||||
uint64_t order) {
|
||||
vieter_heap_tree *next, uint8_t order) {
|
||||
vieter_heap_tree *tree = malloc(sizeof(vieter_heap_tree));
|
||||
|
||||
tree->root = root;
|
||||
|
|
@ -54,7 +84,7 @@ vieter_heap_tree *vieter_heap_tree_merge_same_order(vieter_heap_tree *tree_a,
|
|||
|
||||
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 *tree, *target, *out;
|
||||
|
||||
if (tree_a->order <= tree_b->order) {
|
||||
target = tree_a;
|
||||
|
|
@ -67,7 +97,7 @@ vieter_heap_tree *vieter_heap_tree_merge(vieter_heap_tree *tree_a,
|
|||
vieter_heap_tree *next_tree, *next_target;
|
||||
vieter_heap_tree *previous_target = NULL;
|
||||
|
||||
while (target != NULL && target != NULL) {
|
||||
while (target != NULL && tree != NULL) {
|
||||
if (target->order == tree->order) {
|
||||
next_tree = tree->next;
|
||||
next_target = target->next;
|
||||
|
|
@ -76,38 +106,52 @@ vieter_heap_tree *vieter_heap_tree_merge(vieter_heap_tree *tree_a,
|
|||
|
||||
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
|
||||
// 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 = target->next->next;
|
||||
target = vieter_heap_tree_merge_same_order(target, target->next);
|
||||
target->next = next_target;
|
||||
}
|
||||
|
||||
if (previous_target != NULL) {
|
||||
previous_target->next = target;
|
||||
} else {
|
||||
out = target;
|
||||
}
|
||||
|
||||
tree = next_tree;
|
||||
} else if (target->order > tree->order) {
|
||||
next_tree = tree->next;
|
||||
|
||||
if (previous_target == NULL) {
|
||||
previous_target = tree;
|
||||
out = tree;
|
||||
} else {
|
||||
previous_target->next = tree;
|
||||
}
|
||||
|
||||
tree->next = target;
|
||||
|
||||
tree = tree->next;
|
||||
tree = next_tree;
|
||||
} else {
|
||||
if (previous_target == NULL) {
|
||||
out = target;
|
||||
}
|
||||
|
||||
previous_target = target;
|
||||
target = target->next;
|
||||
}
|
||||
}
|
||||
|
||||
// Append final part of tree to target
|
||||
target->next = tree;
|
||||
if (target == NULL) {
|
||||
previous_target->next = tree;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
vieter_heap_tree *vieter_heap_tree_pop(vieter_heap_tree *tree) {
|
||||
|
||||
return target;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,16 +16,23 @@ vieter_heap_node *vieter_heap_node_init();
|
|||
void vieter_heap_node_free(vieter_heap_node *node);
|
||||
|
||||
typedef struct vieter_heap_tree {
|
||||
uint64_t order;
|
||||
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, uint64_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);
|
||||
|
||||
vieter_heap_tree *vieter_heap_tree_merge(vieter_heap_tree *tree_a, vieter_heap_tree *tree_b);
|
||||
|
||||
vieter_heap_tree *vieter_heap_tree_merge_same_order(vieter_heap_tree *tree_a,
|
||||
vieter_heap_tree *tree_b);
|
||||
|
||||
vieter_heap_tree *vieter_heap_tree_pop(vieter_heap_tree *tree);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Reference in a new issue