diff --git a/include/unicstl.h b/include/unicstl.h index bf4df7d..e8b281c 100644 --- a/include/unicstl.h +++ b/include/unicstl.h @@ -16,5 +16,6 @@ #include "queue.h" #include "deque.h" #include "tree.h" +#include "heap.h" #endif // _UNICSTL_H_ diff --git a/src/heap.c b/src/heap.c index d5e45af..490e159 100644 --- a/src/heap.c +++ b/src/heap.c @@ -8,6 +8,25 @@ */ #include "heap.h" +static int left(int i) +{ + return 2 * i + 1; +} + +static int right(int i) +{ + return (i << 1) + 2; +} + +static int parent(int i) +{ + if(i == 0) + { + return -1; + } + return (i-1) >> 1; +} + bool heap_peek(struct _heap* self, void* obj) { assert(self != NULL); @@ -23,15 +42,60 @@ bool heap_peek(struct _heap* self, void* obj) return true; } +static void heap_swap(struct _heap* self, int i, int j) +{ + assert(self != NULL); + char tmp[self->_obj_size]; + + memmove(tmp, self->obj + i * self->_obj_size, self->_obj_size); + memmove(self->obj + i * self->_obj_size, self->obj + j * self->_obj_size, self->_obj_size); + memmove(self->obj + j * self->_obj_size, tmp, self->_obj_size); +} + +static void heap_fixed(struct _heap* self, int i) +{ + assert(self != NULL); + int p = 0; + while(1) + { + p = parent(i); + if(p < 0 || self->compare(self->obj + i * self->_obj_size, self->obj + p * self->_obj_size) <= 0) + { + break; + } + heap_swap(self, i, p); + i = p; + } +} + bool heap_push(struct _heap* self, void* obj) { assert(self != NULL); - + if(self->size(self) > self->_capacity) + { + return false; + } + uint32_t index = self->size(self); + memmove(self->obj + index * self->_obj_size, obj, self->_obj_size); + self->_size++; + + heap_fixed(self, index); } bool heap_pop(struct _heap* self, void* obj) { assert(self != NULL); + if(self->empty(self)) + { + return false; + } + heap_swap(self, 0, self->size(self) - 1); + if(obj != NULL) + { + memmove(obj, self->obj, self->_obj_size); + } + self->_size--; + heap_fixed(self, 0); } void heap_setmin(struct _heap* self, bool min_flag) @@ -55,11 +119,18 @@ bool heap_empty(struct _heap* self) bool heap_clear(struct _heap* self) { assert(self != NULL); + self->_size = 0; + return true; } void heap_destory(struct _heap* self) { assert(self != NULL); + self->clear(self); + if(self->obj) + { + free(self->obj); + } } void heap_print(struct _heap* self) @@ -73,7 +144,7 @@ void heap_print(struct _heap* self) for (int i = self->size(self) - 1; i >= 0; i--) { offset = self->_obj_size * i; - obj = (char*)self->obj + offset; + obj = (char *)self->obj + offset; self->print_obj(obj); } } diff --git a/test/test.c b/test/test.c index 6dadbeb..e078b7f 100644 --- a/test/test.c +++ b/test/test.c @@ -49,11 +49,12 @@ int main() printf("----- unicstl test -----\n"); // while (1) { - test_list(); - test_stack(); - test_deque(); - test_queue(); - test_tree(); + // test_list(); + // test_stack(); + // test_deque(); + // test_queue(); + // test_tree(); + test_heap(); } printf("----- unicstl ok -----\n"); diff --git a/test/test_heap.c b/test/test_heap.c index 7892a19..9b4cce5 100644 --- a/test/test_heap.c +++ b/test/test_heap.c @@ -12,7 +12,51 @@ void test_heap_num(void) { + uint32_t i = 0; + int data[] = { 2,1,3,4}; + // int data[] = { 1,2,3,4,5,6}; + // int data[] = { 5,2,3,1,7,8,6 }; + // int data[] = { 5,2,3,1,7,8,6,4,9,10,12,11,15,14,13 }; + int temp = 0; + uint32_t len = sizeof(data) / sizeof(data[0]); + heap_t heap = heap_new(); + heap_init2(heap, sizeof(int), 64); + heap->print_obj = print_num; + heap->compare = compare_num; + + printf("\n\n----- test_heap_num -----\n"); + + printf("----- push -----\n"); + for (i = 0; i < len; i++) + { + temp = data[i]; + heap->push(heap, &temp); + + printf("push = "); + heap->print_obj(&temp); + printf("size = %2d : ", heap->size(heap)); + heap->print(heap); + printf("\n"); + } + + printf("----- max -----\n"); + heap->peek(heap, &temp); + heap->print_obj(&temp); + printf("\n"); + + printf("----- heap -----\n"); + heap->clear(heap); + if(heap->empty(heap)) + { + printf("----- empty -----\n"); + } + printf("----- heap -----\n"); + for (i = 0; i < len; i++) + { + temp = data[i]; + heap->push(heap, &temp); + } } void test_heap(void)