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