Compare commits
	
		
			2 Commits 
		
	
	
		
			0ec37a89f2
			...
			63100c5b99
		
	
	| Author | SHA1 | Date | 
|---|---|---|
| 
							
							
								
									
								
								 | 
						63100c5b99 | |
| 
							
							
								
									
								
								 | 
						6845e67cb6 | 
| 
						 | 
					@ -51,23 +51,23 @@ vieter_heap_error vieter_heap_insert(vieter_heap *heap, uint64_t key,
 | 
				
			||||||
  return vieter_heap_ok;
 | 
					  return vieter_heap_ok;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* 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) { */
 | 
					  if (heap->tree == NULL) {
 | 
				
			||||||
/*     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->root->data; */
 | 
					    *out = heap->tree->data;
 | 
				
			||||||
/*     vieter_heap_tree_free(heap->tree); */
 | 
					    vieter_heap_tree_free(heap->tree);
 | 
				
			||||||
/*     heap->tree = NULL; */
 | 
					    heap->tree = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*     return vieter_heap_ok; */
 | 
					    return vieter_heap_ok;
 | 
				
			||||||
/*   } */
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*   vieter_heap_tree_pop(out, heap->tree); */
 | 
					  heap->tree = vieter_heap_tree_pop(out, heap->tree);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*   return vieter_heap_ok; */
 | 
					  return vieter_heap_ok;
 | 
				
			||||||
/* } */
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
vieter_heap_error vieter_heap_peek(void **out, vieter_heap *heap) {
 | 
					vieter_heap_error vieter_heap_peek(void **out, vieter_heap *heap) {
 | 
				
			||||||
  if (heap->tree == NULL) {
 | 
					  if (heap->tree == NULL) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -41,18 +41,6 @@ end:
 | 
				
			||||||
  vieter_heap_node_free(root);
 | 
					  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 *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 *new_root;
 | 
				
			||||||
| 
						 | 
					@ -144,52 +132,61 @@ vieter_heap_node *vieter_heap_tree_merge(vieter_heap_node *root_a,
 | 
				
			||||||
  return out;
 | 
					  return out;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* vieter_heap_tree *vieter_heap_tree_pop(void **out, vieter_heap_tree *tree) {
 | 
					vieter_heap_node *vieter_heap_tree_pop(void **out, vieter_heap_node *tree) {
 | 
				
			||||||
 */
 | 
					  vieter_heap_node *tree_before_smallest = NULL;
 | 
				
			||||||
/*   vieter_heap_tree *tree_before_smallest = NULL; */
 | 
					  vieter_heap_node *previous_tree = NULL;
 | 
				
			||||||
/*   vieter_heap_tree *previous_tree = NULL; */
 | 
					  vieter_heap_node *original_root = tree;
 | 
				
			||||||
/*   vieter_heap_tree *tree_out = tree; */
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*   uint64_t smallest_key = tree->root->key; */
 | 
					  uint64_t smallest_key = tree->key;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*   while (tree->next != NULL) { */
 | 
					  while (tree->ptr.next_tree != NULL) {
 | 
				
			||||||
/*     previous_tree = tree; */
 | 
					    previous_tree = tree;
 | 
				
			||||||
/*     tree = tree->next; */
 | 
					    tree = tree->ptr.next_tree;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*     if (tree->root->key < smallest_key) { */
 | 
					    if (tree->key < smallest_key) {
 | 
				
			||||||
/*       smallest_key = tree->root->key; */
 | 
					      smallest_key = tree->key;
 | 
				
			||||||
/*       *out = tree->root->data; */
 | 
					      tree_before_smallest = previous_tree;
 | 
				
			||||||
/*       tree_before_smallest = previous_tree; */
 | 
					    }
 | 
				
			||||||
/*     } */
 | 
					  }
 | 
				
			||||||
/*   } */
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*   if (tree_before_smallest != NULL) { */
 | 
					  vieter_heap_node *tree_to_pop;
 | 
				
			||||||
/*     previous_tree->next = tree->next; */
 | 
					 | 
				
			||||||
/*   } else { */
 | 
					 | 
				
			||||||
/*     tree_out = tree_out->next; */
 | 
					 | 
				
			||||||
/*   } */
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*   if (tree->order == 0) { */
 | 
					  if (tree_before_smallest != NULL) {
 | 
				
			||||||
/*     vieter_heap_tree_free(tree); */
 | 
					    tree_to_pop = tree_before_smallest->ptr.next_tree;
 | 
				
			||||||
 | 
					    tree_before_smallest->ptr.next_tree = tree_to_pop->ptr.next_tree;
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    tree_to_pop = original_root;
 | 
				
			||||||
 | 
					    original_root = original_root->ptr.next_tree;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*     return NULL; */
 | 
					  *out = tree_to_pop->data;
 | 
				
			||||||
/*   } */
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*   uint8_t old_order = tree->order; */
 | 
					  if (tree_to_pop->order == 0) {
 | 
				
			||||||
 | 
					    vieter_heap_tree_free(tree_to_pop);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*   vieter_heap_node *node = tree->root->largest_order; */
 | 
					    return original_root;
 | 
				
			||||||
/*   free(tree->root); */
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*   previous_tree = vieter_heap_tree_init(node, NULL, old_order - 1); */
 | 
					  previous_tree = tree_to_pop->largest_order;
 | 
				
			||||||
 | 
					  vieter_heap_node_free(tree_to_pop);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*   uint8_t i = 2; */
 | 
					  tree = previous_tree->ptr.next_largest_order;
 | 
				
			||||||
/*   while (node->next_largest_order != NULL) { */
 | 
					  previous_tree->ptr.next_tree = NULL;
 | 
				
			||||||
/*     node = node->next_largest_order; */
 | 
					 | 
				
			||||||
/*     previous_tree = vieter_heap_tree_init(node, previous_tree, old_order -
 | 
					 | 
				
			||||||
 * i); */
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*     i++; */
 | 
					  vieter_heap_node *next_tree;
 | 
				
			||||||
/*   } */
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*   return vieter_heap_tree_merge(tree_out, previous_tree); */
 | 
					  while (tree != NULL) {
 | 
				
			||||||
/* } */
 | 
					    next_tree = tree->ptr.next_largest_order;
 | 
				
			||||||
 | 
					    tree->ptr.next_tree = previous_tree;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    previous_tree = tree;
 | 
				
			||||||
 | 
					    tree = next_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 {
 | 
				
			||||||
 | 
					      // Roots point to next tree in the heap, other nodes point to their first
 | 
				
			||||||
 | 
					      // neighbour.
 | 
				
			||||||
      struct vieter_heap_node *next_tree;
 | 
					      struct vieter_heap_node *next_tree;
 | 
				
			||||||
      struct vieter_heap_node *next_largest_order;
 | 
					      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); \
 | 
				
			||||||
| 
						 | 
					@ -51,35 +52,82 @@ void test_insert() {
 | 
				
			||||||
    vieter_heap_free(heap);
 | 
					    vieter_heap_free(heap);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* void test_pop() { */
 | 
					void test_pop() {
 | 
				
			||||||
/*     vieter_heap *heap = vieter_heap_init(); */
 | 
					    vieter_heap *heap = vieter_heap_init();
 | 
				
			||||||
/*     TEST_SIZE(heap, 0); */
 | 
					    TEST_SIZE(heap, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*     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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*         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; */
 | 
					    data = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*     for (uint64_t i = 1; i <= 50; i++) { */
 | 
					    for (uint64_t i = 1; i <= 50; i++) {
 | 
				
			||||||
/*         TEST_CHECK(vieter_heap_pop(&data, heap) == vieter_heap_ok); */
 | 
					        TEST_CHECK(vieter_heap_pop(&data, heap) == vieter_heap_ok);
 | 
				
			||||||
/*         TEST_CHECK(data == (void*)i); */
 | 
					        TEST_CHECK(data == (void*)i);
 | 
				
			||||||
/*         TEST_SIZE(heap, (uint64_t)50 - i); */
 | 
					        TEST_SIZE(heap, (uint64_t)50 - i);
 | 
				
			||||||
/*     } */
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*     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