diff --git a/src/heap/vieter_heap_tree.c b/src/heap/vieter_heap_tree.c index e65fb56..75b38d2 100644 --- a/src/heap/vieter_heap_tree.c +++ b/src/heap/vieter_heap_tree.c @@ -4,24 +4,6 @@ vieter_heap_node *vieter_heap_node_init() { return calloc(1, sizeof(vieter_heap_node)); } -vieter_heap_node *vieter_heap_node_merge_same_order(vieter_heap_node *root_a, - vieter_heap_node *root_b) { - vieter_heap_node *new_root, *new_child; - - if (root_a->key <= root_b->key) { - new_root = root_a; - new_child = root_b; - } else { - new_root = root_b; - new_child = root_a; - } - - new_root->next_largest_order = new_root->largest_order; - new_root->largest_order = new_child; - - return new_root; -} - vieter_heap_tree *vieter_heap_tree_init(vieter_heap_node *root, vieter_heap_tree *next, uint64_t order) { @@ -34,5 +16,93 @@ vieter_heap_tree *vieter_heap_tree_init(vieter_heap_node *root, return tree; } -vieter_heap_tree *vieter_heap_tree_merge(vieter_heap_tree *tree_a, - vieter_heap_tree *tree_b) {} +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 = 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/src/heap/vieter_heap_tree.h b/src/heap/vieter_heap_tree.h index 18808e1..03b61a4 100644 --- a/src/heap/vieter_heap_tree.h +++ b/src/heap/vieter_heap_tree.h @@ -15,8 +15,6 @@ vieter_heap_node *vieter_heap_node_init(); void vieter_heap_node_free(vieter_heap_node *node); -vieter_heap_node *vieter_heap_tree_merge_same_order(vieter_heap_node *root_a, vieter_heap_node *root_b); - typedef struct vieter_heap_tree { uint64_t order; vieter_heap_node *root; @@ -27,4 +25,7 @@ vieter_heap_tree *vieter_heap_tree_init(vieter_heap_node *root, vieter_heap_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); + #endif