#include "vieter_heap_tree.h" 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_node *root) { if (root->order == 0) { goto end; } uint64_t size = 1; vieter_heap_node **stack = malloc(((uint64_t)1 << root->order) * sizeof(vieter_heap_node *)); stack[0] = root->largest_order; 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->ptr.next_largest_order != NULL) { stack[size] = node->ptr.next_largest_order; size++; } vieter_heap_node_free(node); } free(stack); end: vieter_heap_node_free(root); } /* vieter_heap_tree *vieter_heap_tree_init(vieter_heap_node *root, */ /* vieter_heap_tree *next, uint8_t * order) { */ /* vieter_heap_tree *tree = malloc(sizeof(vieter_heap_tree)); */ /* tree->root = root; */ /* tree->next = next; */ /* tree->order = order; */ /* return tree; */ /* } */ vieter_heap_node *vieter_heap_tree_merge_same_order(vieter_heap_node *root_a, vieter_heap_node *root_b) { vieter_heap_node *new_root; 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; } else { new_root = root_b; root_a->ptr.next_largest_order = root_b->largest_order; root_b->largest_order = root_a; } new_root->order++; return new_root; } vieter_heap_node *vieter_heap_tree_merge(vieter_heap_node *root_a, vieter_heap_node *root_b) { vieter_heap_node *root, *target, *out; if (root_a->order <= root_b->order) { target = root_a; root = root_b; } else { target = root_b; root = root_a; } vieter_heap_node *next_tree, *next_target; vieter_heap_node *previous_target = NULL; while (target != NULL && root != NULL) { if (target->order == root->order) { next_tree = root->ptr.next_tree; next_target = target->ptr.next_tree; target = vieter_heap_tree_merge_same_order(target, root); target->ptr.next_tree = next_target; // 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; } if (previous_target != NULL) { previous_target->ptr.next_tree = target; } else { out = target; } root = next_tree; } else if (target->order > root->order) { next_tree = root->ptr.next_tree; if (previous_target == NULL) { previous_target = root; out = root; } else { previous_target->ptr.next_tree = root; } root->ptr.next_tree = target; root = next_tree; } else { if (previous_target == NULL) { out = target; } previous_target = target; target = target->ptr.next_tree; } } // Append final part of tree to target if (target == NULL) { previous_target->ptr.next_tree = root; } return out; } /* vieter_heap_tree *vieter_heap_tree_pop(void **out, vieter_heap_tree *tree) { */ /* vieter_heap_tree *tree_before_smallest = NULL; */ /* vieter_heap_tree *previous_tree = NULL; */ /* vieter_heap_tree *tree_out = tree; */ /* uint64_t smallest_key = tree->root->key; */ /* while (tree->next != NULL) { */ /* previous_tree = tree; */ /* tree = tree->next; */ /* if (tree->root->key < smallest_key) { */ /* smallest_key = tree->root->key; */ /* *out = tree->root->data; */ /* tree_before_smallest = previous_tree; */ /* } */ /* } */ /* if (tree_before_smallest != NULL) { */ /* previous_tree->next = tree->next; */ /* } else { */ /* tree_out = tree_out->next; */ /* } */ /* if (tree->order == 0) { */ /* vieter_heap_tree_free(tree); */ /* return NULL; */ /* } */ /* uint8_t old_order = tree->order; */ /* vieter_heap_node *node = tree->root->largest_order; */ /* free(tree->root); */ /* previous_tree = vieter_heap_tree_init(node, NULL, old_order - 1); */ /* uint8_t i = 2; */ /* while (node->next_largest_order != NULL) { */ /* node = node->next_largest_order; */ /* previous_tree = vieter_heap_tree_init(node, previous_tree, old_order - * i); */ /* i++; */ /* } */ /* return vieter_heap_tree_merge(tree_out, previous_tree); */ /* } */