Compare commits
	
		
			2 Commits 
		
	
	
		
			0ec37a89f2
			...
			63100c5b99
		
	
	| Author | SHA1 | Date | 
|---|---|---|
|  | 63100c5b99 | |
|  | 6845e67cb6 | 
|  | @ -56,7 +56,7 @@ vieter_heap_error vieter_heap_pop(void **out, vieter_heap *heap) { | ||||||
|     return vieter_heap_empty; |     return vieter_heap_empty; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   if (heap->tree->order == 0) { |   if (heap->tree->order == 0 && heap->tree->ptr.next_tree == NULL) { | ||||||
|     *out = heap->tree->data; |     *out = heap->tree->data; | ||||||
|     vieter_heap_tree_free(heap->tree); |     vieter_heap_tree_free(heap->tree); | ||||||
|     heap->tree = NULL; |     heap->tree = NULL; | ||||||
|  |  | ||||||
|  | @ -162,7 +162,7 @@ vieter_heap_node *vieter_heap_tree_pop(void **out, vieter_heap_node *tree) { | ||||||
|   *out = tree_to_pop->data; |   *out = tree_to_pop->data; | ||||||
| 
 | 
 | ||||||
|   if (tree_to_pop->order == 0) { |   if (tree_to_pop->order == 0) { | ||||||
|     vieter_heap_tree_free(tree); |     vieter_heap_tree_free(tree_to_pop); | ||||||
| 
 | 
 | ||||||
|     return original_root; |     return original_root; | ||||||
|   } |   } | ||||||
|  | @ -183,5 +183,10 @@ vieter_heap_node *vieter_heap_tree_pop(void **out, vieter_heap_node *tree) { | ||||||
|     tree = next_tree; |     tree = next_tree; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   return vieter_heap_tree_merge(original_root, previous_tree); |   // original_root is zero if the heap only contained a single tree.
 | ||||||
|  |   if (original_root != NULL) { | ||||||
|  |     return vieter_heap_tree_merge(original_root, previous_tree); | ||||||
|  |   } else { | ||||||
|  |     return previous_tree; | ||||||
|  |   } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -9,28 +9,45 @@ typedef struct vieter_heap_node { | ||||||
|     void *data; |     void *data; | ||||||
|     struct vieter_heap_node *largest_order; |     struct vieter_heap_node *largest_order; | ||||||
|     union { |     union { | ||||||
|         struct vieter_heap_node *next_tree; |       // Roots point to next tree in the heap, other nodes point to their first
 | ||||||
|         struct vieter_heap_node *next_largest_order; |       // neighbour.
 | ||||||
|  |       struct vieter_heap_node *next_tree; | ||||||
|  |       struct vieter_heap_node *next_largest_order; | ||||||
|     } ptr; |     } ptr; | ||||||
|     uint8_t order; |     uint8_t order; | ||||||
| } vieter_heap_node; | } vieter_heap_node; | ||||||
| 
 | 
 | ||||||
|  | /*
 | ||||||
|  |  * Allocate an initialize a heap node object. | ||||||
|  |  */ | ||||||
| vieter_heap_node *vieter_heap_node_init(); | vieter_heap_node *vieter_heap_node_init(); | ||||||
| 
 | 
 | ||||||
|  | /*
 | ||||||
|  |  * Deallocate a node object. | ||||||
|  |  */ | ||||||
| void vieter_heap_node_free(vieter_heap_node *node); | void vieter_heap_node_free(vieter_heap_node *node); | ||||||
| 
 | 
 | ||||||
| /* 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. |  * Deallocate a node's entire structure. | ||||||
|  */ |  */ | ||||||
| void vieter_heap_tree_free(vieter_heap_node *root); | void vieter_heap_tree_free(vieter_heap_node *root); | ||||||
| 
 | 
 | ||||||
|  | /*
 | ||||||
|  |  * Given the roots of the smallest trees in two heaps, merge them into a single | ||||||
|  |  * large heap. | ||||||
|  |  */ | ||||||
| vieter_heap_node *vieter_heap_tree_merge(vieter_heap_node *root_a, vieter_heap_node *root_b); | vieter_heap_node *vieter_heap_tree_merge(vieter_heap_node *root_a, vieter_heap_node *root_b); | ||||||
| 
 | 
 | ||||||
|  | /*
 | ||||||
|  |  * Given the roots of two trees of the same order, merge them into a heap of one | ||||||
|  |  * order larger. | ||||||
|  |  */ | ||||||
| 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); | ||||||
| 
 | 
 | ||||||
|  | /*
 | ||||||
|  |  * Remove the smallest element from the given heap. | ||||||
|  |  */ | ||||||
| vieter_heap_node *vieter_heap_tree_pop(void **out, vieter_heap_node *root); | vieter_heap_node *vieter_heap_tree_pop(void **out, vieter_heap_node *root); | ||||||
| 
 | 
 | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | @ -1,6 +1,7 @@ | ||||||
| #include "acutest.h" | #include "acutest.h" | ||||||
| #include "vieter_heap.h" | #include "vieter_heap.h" | ||||||
| #include "vieter_heap_tree.h" | #include "vieter_heap_tree.h" | ||||||
|  | #include <stdlib.h> | ||||||
| 
 | 
 | ||||||
| #define TEST_SIZE(heap, size) \ | #define TEST_SIZE(heap, size) \ | ||||||
|     TEST_CHECK(vieter_heap_size(heap) == size); \ |     TEST_CHECK(vieter_heap_size(heap) == size); \ | ||||||
|  | @ -76,10 +77,57 @@ void test_pop() { | ||||||
|     vieter_heap_free(heap); |     vieter_heap_free(heap); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | int uint64_t_compare(const void *a, const void *b) { | ||||||
|  |     if ((*(uint64_t *)a) < (*(uint64_t *)b)) { | ||||||
|  |         return -1; | ||||||
|  |     } else if ((*(uint64_t *)a) < (*(uint64_t *)b)) { | ||||||
|  |         return 1; | ||||||
|  |     } else { | ||||||
|  |         return 0; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void test_pop_random() { | ||||||
|  |     srand(0); | ||||||
|  | 
 | ||||||
|  |     vieter_heap *heap = vieter_heap_init(); | ||||||
|  | 
 | ||||||
|  |     uint64_t *numbers = malloc(500 * sizeof(uint64_t)); | ||||||
|  |     uint64_t num; | ||||||
|  | 
 | ||||||
|  |     for (uint64_t i = 0; i < 500; i++) { | ||||||
|  |         num = rand(); | ||||||
|  |         vieter_heap_insert(heap, num, (void *)num); | ||||||
|  |         TEST_SIZE(heap, i + 1); | ||||||
|  | 
 | ||||||
|  |         numbers[i] = num; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     qsort(numbers, 500, sizeof(uint64_t), uint64_t_compare); | ||||||
|  | 
 | ||||||
|  |     void *data = NULL; | ||||||
|  | 
 | ||||||
|  |     for (uint64_t i = 0; i < 500; i++) { | ||||||
|  |         TEST_CHECK(vieter_heap_peek(&data, heap) == vieter_heap_ok); | ||||||
|  |         TEST_CHECK(data == (void *)numbers[i]); | ||||||
|  | 
 | ||||||
|  |         data = NULL; | ||||||
|  | 
 | ||||||
|  |         TEST_CHECK(vieter_heap_pop(&data, heap) == vieter_heap_ok); | ||||||
|  |         TEST_CHECK(data == (void *)numbers[i]); | ||||||
|  |         TEST_SIZE(heap, (uint64_t)500 - i - 1); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     vieter_heap_free(heap); | ||||||
|  |     free(numbers); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| TEST_LIST = { | TEST_LIST = { | ||||||
|     {"init", test_init}, |     {"init", test_init}, | ||||||
|     {"merge same order", test_merge_same_order}, |     {"merge same order", test_merge_same_order}, | ||||||
|     {"insert", test_insert}, |     {"insert", test_insert}, | ||||||
|     {"pop", test_pop}, |     {"pop", test_pop}, | ||||||
|  |     {"pop random", test_pop_random}, | ||||||
|     {NULL, NULL} |     {NULL, NULL} | ||||||
| }; | }; | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue