refactor(heap): some better variable names; some more tests
							parent
							
								
									dc557f57ab
								
							
						
					
					
						commit
						3ec2e76af9
					
				| 
						 | 
					@ -1,12 +1,7 @@
 | 
				
			||||||
#include "vieter_heap.h"
 | 
					#include "vieter_heap_internal.h"
 | 
				
			||||||
#include "vieter_heap_tree.h"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <stdlib.h>
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct vieter_heap {
 | 
					 | 
				
			||||||
  vieter_heap_node *tree;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
vieter_heap *vieter_heap_init() { return calloc(1, sizeof(vieter_heap)); }
 | 
					vieter_heap *vieter_heap_init() { return calloc(1, sizeof(vieter_heap)); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
uint64_t vieter_heap_size(vieter_heap *heap) {
 | 
					uint64_t vieter_heap_size(vieter_heap *heap) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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 *vieter_heap_tree_merge_same_order(vieter_heap_node *root_a,
 | 
				
			||||||
                                                    vieter_heap_node *root_b) {
 | 
					                                                    vieter_heap_node *root_b) {
 | 
				
			||||||
  vieter_heap_node *new_root;
 | 
					  vieter_heap_node *root, *child;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (root_a->key <= root_b->key) {
 | 
					  if (root_a->key <= root_b->key) {
 | 
				
			||||||
    new_root = root_a;
 | 
					    root = root_a;
 | 
				
			||||||
    root_b->ptr.next_largest_order = root_a->largest_order;
 | 
					    child = root_b;
 | 
				
			||||||
    root_a->largest_order = root_b;
 | 
					 | 
				
			||||||
  } else {
 | 
					  } else {
 | 
				
			||||||
    new_root = root_b;
 | 
					    root = root_b;
 | 
				
			||||||
    root_a->ptr.next_largest_order = root_b->largest_order;
 | 
					    child = root_a;
 | 
				
			||||||
    root_b->largest_order = 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 *vieter_heap_tree_merge(vieter_heap_node *root_a,
 | 
				
			||||||
                                         vieter_heap_node *root_b) {
 | 
					                                         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) {
 | 
					  if (root_a->order <= root_b->order) {
 | 
				
			||||||
    target = root_a;
 | 
					    target_tree = root_a;
 | 
				
			||||||
    root = root_b;
 | 
					    other_tree = root_b;
 | 
				
			||||||
  } else {
 | 
					  } else {
 | 
				
			||||||
    target = root_b;
 | 
					    target_tree = root_b;
 | 
				
			||||||
    root = root_a;
 | 
					    other_tree = root_a;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  vieter_heap_node *next_tree, *next_target;
 | 
					  vieter_heap_node *next_other_tree, *next_target_tree;
 | 
				
			||||||
  vieter_heap_node *previous_target = NULL;
 | 
					  vieter_heap_node *previous_target_tree = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  while (target != NULL && root != NULL) {
 | 
					  while (target_tree != NULL && other_tree != NULL) {
 | 
				
			||||||
    if (target->order == root->order) {
 | 
					    if (target_tree->order == other_tree->order) {
 | 
				
			||||||
      next_tree = root->ptr.next_tree;
 | 
					      next_other_tree = other_tree->ptr.next_tree;
 | 
				
			||||||
      next_target = target->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
 | 
					      // 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
 | 
					      // 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->ptr.next_tree != NULL &&
 | 
					      while (next_target_tree != NULL &&
 | 
				
			||||||
             target->ptr.next_tree->order == target->order) {
 | 
					             next_target_tree->order == target_tree->order) {
 | 
				
			||||||
        next_target = target->ptr.next_tree->ptr.next_tree;
 | 
					        next_target_tree = next_target_tree->ptr.next_tree;
 | 
				
			||||||
        target =
 | 
					        target_tree = vieter_heap_tree_merge_same_order(
 | 
				
			||||||
            vieter_heap_tree_merge_same_order(target, target->ptr.next_tree);
 | 
					            target_tree, target_tree->ptr.next_tree);
 | 
				
			||||||
        target->ptr.next_tree = next_target;
 | 
					        target_tree->ptr.next_tree = next_target_tree;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      if (previous_target != NULL) {
 | 
					      if (previous_target_tree != NULL) {
 | 
				
			||||||
        previous_target->ptr.next_tree = target;
 | 
					        previous_target_tree->ptr.next_tree = target_tree;
 | 
				
			||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
        out = target;
 | 
					        out = target_tree;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      root = next_tree;
 | 
					      other_tree = next_other_tree;
 | 
				
			||||||
    } else if (target->order > root->order) {
 | 
					    } else if (target_tree->order > other_tree->order) {
 | 
				
			||||||
      next_tree = root->ptr.next_tree;
 | 
					      next_other_tree = other_tree->ptr.next_tree;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      if (previous_target == NULL) {
 | 
					      if (previous_target_tree == NULL) {
 | 
				
			||||||
        previous_target = root;
 | 
					        previous_target_tree = other_tree;
 | 
				
			||||||
        out = root;
 | 
					        out = other_tree;
 | 
				
			||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
        previous_target->ptr.next_tree = root;
 | 
					        previous_target_tree->ptr.next_tree = other_tree;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      root->ptr.next_tree = target;
 | 
					      other_tree->ptr.next_tree = target_tree;
 | 
				
			||||||
      root = next_tree;
 | 
					      other_tree = next_other_tree;
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      if (previous_target == NULL) {
 | 
					      if (previous_target_tree == NULL) {
 | 
				
			||||||
        out = target;
 | 
					        out = target_tree;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      previous_target = target;
 | 
					      previous_target_tree = target_tree;
 | 
				
			||||||
      target = target->ptr.next_tree;
 | 
					      target_tree = target_tree->ptr.next_tree;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Append final part of tree to target
 | 
					  // Append final part of tree to target
 | 
				
			||||||
  if (target == NULL) {
 | 
					  if (target_tree == NULL) {
 | 
				
			||||||
    previous_target->ptr.next_tree = root;
 | 
					    previous_target_tree->ptr.next_tree = other_tree;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return out;
 | 
					  return out;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,5 @@
 | 
				
			||||||
#include "acutest.h"
 | 
					#include "acutest.h"
 | 
				
			||||||
#include "vieter_heap.h"
 | 
					#include "vieter_heap_internal.h"
 | 
				
			||||||
#include "vieter_heap_tree.h"
 | 
					 | 
				
			||||||
#include <stdlib.h>
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define TEST_SIZE(heap, size) \
 | 
					#define TEST_SIZE(heap, size) \
 | 
				
			||||||
| 
						 | 
					@ -14,6 +13,29 @@ void test_init() {
 | 
				
			||||||
    vieter_heap_free(heap);
 | 
					    vieter_heap_free(heap);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void count_nodes(uint64_t *counter, vieter_heap_node *root) {
 | 
				
			||||||
 | 
					    (*counter)++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (root->largest_order != NULL) {
 | 
				
			||||||
 | 
					        count_nodes(counter, root->largest_order);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // This will also traverse the various trees
 | 
				
			||||||
 | 
					    if (root->ptr.next_largest_order != NULL) {
 | 
				
			||||||
 | 
					        count_nodes(counter, root->ptr.next_largest_order);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint64_t count_nodes_heap(vieter_heap *heap) {
 | 
				
			||||||
 | 
					    uint64_t counter = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (heap->tree != NULL) {
 | 
				
			||||||
 | 
					        count_nodes(&counter, heap->tree);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return counter;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void test_insert() {
 | 
					void test_insert() {
 | 
				
			||||||
    vieter_heap *heap = vieter_heap_init();
 | 
					    vieter_heap *heap = vieter_heap_init();
 | 
				
			||||||
    TEST_SIZE(heap, 0);
 | 
					    TEST_SIZE(heap, 0);
 | 
				
			||||||
| 
						 | 
					@ -23,6 +45,7 @@ void test_insert() {
 | 
				
			||||||
    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);
 | 
				
			||||||
 | 
					        TEST_CHECK(count_nodes_heap(heap) == (uint64_t)51 - i);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        data = 0;
 | 
					        data = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -47,6 +70,7 @@ void test_insert_random() {
 | 
				
			||||||
    for (uint64_t i = 0; i < 5000; i++) {
 | 
					    for (uint64_t i = 0; i < 5000; i++) {
 | 
				
			||||||
        vieter_heap_insert(heap, num, (void *)num);
 | 
					        vieter_heap_insert(heap, num, (void *)num);
 | 
				
			||||||
        TEST_SIZE(heap, i + 1);
 | 
					        TEST_SIZE(heap, i + 1);
 | 
				
			||||||
 | 
					        TEST_CHECK(count_nodes_heap(heap) == (uint64_t)i + 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (num < smallest) {
 | 
					        if (num < smallest) {
 | 
				
			||||||
            smallest = num;
 | 
					            smallest = num;
 | 
				
			||||||
| 
						 | 
					@ -72,6 +96,7 @@ void test_pop() {
 | 
				
			||||||
    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);
 | 
				
			||||||
 | 
					        TEST_CHECK(count_nodes_heap(heap) == (uint64_t)51 - 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);
 | 
				
			||||||
| 
						 | 
					@ -112,6 +137,7 @@ void test_pop_random() {
 | 
				
			||||||
        num = rand();
 | 
					        num = rand();
 | 
				
			||||||
        vieter_heap_insert(heap, num, (void *)num);
 | 
					        vieter_heap_insert(heap, num, (void *)num);
 | 
				
			||||||
        TEST_SIZE(heap, i + 1);
 | 
					        TEST_SIZE(heap, i + 1);
 | 
				
			||||||
 | 
					        TEST_CHECK(count_nodes_heap(heap) == i + 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        numbers[i] = num;
 | 
					        numbers[i] = num;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -130,6 +156,7 @@ void test_pop_random() {
 | 
				
			||||||
        TEST_CHECK(vieter_heap_pop(&data, heap) == vieter_heap_ok);
 | 
					        TEST_CHECK(vieter_heap_pop(&data, heap) == vieter_heap_ok);
 | 
				
			||||||
        TEST_CHECK_(data == (void *)numbers[i], "pop %lx == %lx", (uint64_t)data, numbers[i]);
 | 
					        TEST_CHECK_(data == (void *)numbers[i], "pop %lx == %lx", (uint64_t)data, numbers[i]);
 | 
				
			||||||
        TEST_SIZE(heap, n - i - 1);
 | 
					        TEST_SIZE(heap, n - i - 1);
 | 
				
			||||||
 | 
					        TEST_CHECK(count_nodes_heap(heap) == n - i - 1);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    vieter_heap_free(heap);
 | 
					    vieter_heap_free(heap);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue