forked from vieter-v/libvieter
				
			fix(heap): some insert fixes
							parent
							
								
									c1ad26cf0c
								
							
						
					
					
						commit
						3c8c33b47a
					
				| 
						 | 
					@ -14,7 +14,7 @@ uint64_t vieter_heap_size(vieter_heap *heap) {
 | 
				
			||||||
  vieter_heap_tree *tree = heap->tree;
 | 
					  vieter_heap_tree *tree = heap->tree;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  while (tree != NULL) {
 | 
					  while (tree != NULL) {
 | 
				
			||||||
    size |= 1 << tree->order;
 | 
					    size |= (uint64_t)1 << tree->order;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    tree = tree->next;
 | 
					    tree = tree->next;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
| 
						 | 
					@ -22,14 +22,25 @@ uint64_t vieter_heap_size(vieter_heap *heap) {
 | 
				
			||||||
  return size;
 | 
					  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,
 | 
					vieter_heap_error vieter_heap_insert(vieter_heap *heap, uint64_t key,
 | 
				
			||||||
                                     void *data) {
 | 
					                                     void *data) {
 | 
				
			||||||
  vieter_heap_node *new_node = vieter_heap_node_init();
 | 
					  vieter_heap_node *new_node = vieter_heap_node_init();
 | 
				
			||||||
  new_node->key = key;
 | 
					  new_node->key = key;
 | 
				
			||||||
  new_node->data = data;
 | 
					  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) {
 | 
					  if (heap->tree == NULL) {
 | 
				
			||||||
    heap->tree = new_tree;
 | 
					    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) {
 | 
					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;
 | 
					  return vieter_heap_ok;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -49,17 +72,17 @@ vieter_heap_error vieter_heap_peek(void **out, vieter_heap *heap) {
 | 
				
			||||||
    return vieter_heap_empty;
 | 
					    return vieter_heap_empty;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  uint64_t smallest_key;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  vieter_heap_tree *tree = heap->tree;
 | 
					  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) {
 | 
					    if (tree->root->key < smallest_key) {
 | 
				
			||||||
      smallest_key = tree->root->key;
 | 
					      smallest_key = tree->root->key;
 | 
				
			||||||
      *out = tree->root->data;
 | 
					      *out = tree->root->data;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    tree = tree->next;
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return vieter_heap_ok;
 | 
					  return vieter_heap_ok;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,9 +4,39 @@ vieter_heap_node *vieter_heap_node_init() {
 | 
				
			||||||
  return calloc(1, sizeof(vieter_heap_node));
 | 
					  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 *vieter_heap_tree_init(vieter_heap_node *root,
 | 
				
			||||||
                                        vieter_heap_tree *next,
 | 
					                                        vieter_heap_tree *next, uint8_t order) {
 | 
				
			||||||
                                        uint64_t order) {
 | 
					 | 
				
			||||||
  vieter_heap_tree *tree = malloc(sizeof(vieter_heap_tree));
 | 
					  vieter_heap_tree *tree = malloc(sizeof(vieter_heap_tree));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  tree->root = root;
 | 
					  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 *vieter_heap_tree_merge(vieter_heap_tree *tree_a,
 | 
				
			||||||
                                         vieter_heap_tree *tree_b) {
 | 
					                                         vieter_heap_tree *tree_b) {
 | 
				
			||||||
  vieter_heap_tree *tree, *target;
 | 
					  vieter_heap_tree *tree, *target, *out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (tree_a->order <= tree_b->order) {
 | 
					  if (tree_a->order <= tree_b->order) {
 | 
				
			||||||
    target = tree_a;
 | 
					    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 *next_tree, *next_target;
 | 
				
			||||||
  vieter_heap_tree *previous_target = NULL;
 | 
					  vieter_heap_tree *previous_target = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  while (target != NULL && target != NULL) {
 | 
					  while (target != NULL && tree != NULL) {
 | 
				
			||||||
    if (target->order == tree->order) {
 | 
					    if (target->order == tree->order) {
 | 
				
			||||||
      next_tree = tree->next;
 | 
					      next_tree = tree->next;
 | 
				
			||||||
      next_target = target->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;
 | 
					      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
 | 
					      // 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.
 | 
					      // trees until we no longer have a duplicate depth.
 | 
				
			||||||
      while (target->next != NULL && target->next->order == target->order) {
 | 
					      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 = vieter_heap_tree_merge_same_order(target, target->next);
 | 
				
			||||||
        target->next = next_target;
 | 
					        target->next = next_target;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (previous_target != NULL) {
 | 
				
			||||||
 | 
					        previous_target->next = target;
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        out = target;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      tree = next_tree;
 | 
				
			||||||
    } else if (target->order > tree->order) {
 | 
					    } else if (target->order > tree->order) {
 | 
				
			||||||
 | 
					        next_tree = tree->next;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      if (previous_target == NULL) {
 | 
					      if (previous_target == NULL) {
 | 
				
			||||||
        previous_target = tree;
 | 
					        previous_target = tree;
 | 
				
			||||||
 | 
					        out = tree;
 | 
				
			||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
        previous_target->next = tree;
 | 
					        previous_target->next = tree;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      tree->next = target;
 | 
					      tree->next = target;
 | 
				
			||||||
 | 
					      tree = next_tree;
 | 
				
			||||||
      tree = tree->next;
 | 
					 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
 | 
					      if (previous_target == NULL) {
 | 
				
			||||||
 | 
					        out = target;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      previous_target = target;
 | 
					      previous_target = target;
 | 
				
			||||||
      target = target->next;
 | 
					      target = target->next;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Append final part of tree to target
 | 
					  // 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);
 | 
					void vieter_heap_node_free(vieter_heap_node *node);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct vieter_heap_tree {
 | 
					typedef struct vieter_heap_tree {
 | 
				
			||||||
    uint64_t order;
 | 
					    uint8_t order;
 | 
				
			||||||
    vieter_heap_node *root;
 | 
					    vieter_heap_node *root;
 | 
				
			||||||
    struct vieter_heap_tree *next;
 | 
					    struct vieter_heap_tree *next;
 | 
				
			||||||
} vieter_heap_tree;
 | 
					} 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(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 *vieter_heap_tree_merge_same_order(vieter_heap_tree *tree_a,
 | 
				
			||||||
                                                    vieter_heap_tree *tree_b);
 | 
					                                                    vieter_heap_tree *tree_b);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					vieter_heap_tree *vieter_heap_tree_pop(vieter_heap_tree *tree);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -28,6 +28,8 @@ void test_merge_same_order() {
 | 
				
			||||||
    TEST_CHECK(merged->root->key == 1);
 | 
					    TEST_CHECK(merged->root->key == 1);
 | 
				
			||||||
    TEST_CHECK(merged->root->largest_order == root_b);
 | 
					    TEST_CHECK(merged->root->largest_order == root_b);
 | 
				
			||||||
    TEST_CHECK(merged->root->next_largest_order == NULL);
 | 
					    TEST_CHECK(merged->root->next_largest_order == NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    vieter_heap_tree_free(merged);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void test_insert() {
 | 
					void test_insert() {
 | 
				
			||||||
| 
						 | 
					@ -36,18 +38,47 @@ void test_insert() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void *data;
 | 
					    void *data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (uint64_t i = 50; i <= 0; i--) {
 | 
					    for (uint64_t i = 50; i > 0; i--) {
 | 
				
			||||||
        vieter_heap_insert(heap, i, (void *)i);
 | 
					        vieter_heap_insert(heap, i, (void *)i);
 | 
				
			||||||
        TEST_SIZE(heap, (uint64_t)51 - i);
 | 
					        TEST_SIZE(heap, (uint64_t)51 - i);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        data = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        TEST_CHECK(vieter_heap_peek(&data, heap) == vieter_heap_ok);
 | 
				
			||||||
 | 
					        TEST_CHECK_(data == (void *)i, "%lX == %lX", (uint64_t)data, i);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    vieter_heap_free(heap);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void test_pop() {
 | 
				
			||||||
 | 
					    vieter_heap *heap = vieter_heap_init();
 | 
				
			||||||
 | 
					    TEST_SIZE(heap, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void *data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (uint64_t i = 50; i > 0; i--) {
 | 
				
			||||||
 | 
					        vieter_heap_insert(heap, i, (void *)i);
 | 
				
			||||||
 | 
					        TEST_SIZE(heap, (uint64_t)50 - i);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        TEST_CHECK(vieter_heap_peek(&data, heap) == vieter_heap_ok);
 | 
					        TEST_CHECK(vieter_heap_peek(&data, heap) == vieter_heap_ok);
 | 
				
			||||||
        TEST_CHECK(data == (void*)i);
 | 
					        TEST_CHECK(data == (void*)i);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    data = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (uint64_t i = 1; i <= 50; i++) {
 | 
				
			||||||
 | 
					        TEST_CHECK(vieter_heap_pop(&data, heap) == vieter_heap_ok);
 | 
				
			||||||
 | 
					        TEST_CHECK(data == (void*)i);
 | 
				
			||||||
 | 
					        TEST_SIZE(heap, (uint64_t)50 - i);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    vieter_heap_free(heap);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TEST_LIST = {
 | 
					TEST_LIST = {
 | 
				
			||||||
    {"test_init", test_init},
 | 
					    {"init", test_init},
 | 
				
			||||||
    {"test_merge_same_order", test_merge_same_order},
 | 
					    {"merge same order", test_merge_same_order},
 | 
				
			||||||
    {"test_insert", test_insert},
 | 
					    {"insert", test_insert},
 | 
				
			||||||
    {NULL, NULL}
 | 
					    {NULL, NULL}
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue