| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| |
|
| | #include <stdio.h> |
| | #include <stdlib.h> |
| | #include <string.h> |
| | #include <assert.h> |
| |
|
| | #include <pocketsphinx/err.h> |
| |
|
| | #include "util/heap.h" |
| | #include "util/ckd_alloc.h" |
| |
|
| | |
| | |
| | |
| | typedef struct heapnode_s { |
| | void *data; |
| | int32 val; |
| | |
| | int32 nl, nr; |
| | struct heapnode_s *l; |
| | struct heapnode_s *r; |
| | } heapnode_t; |
| |
|
| | |
| | |
| | |
| | struct heap_s { |
| | heapnode_t *top; |
| | }; |
| |
|
| |
|
| | #if 0 |
| | static void |
| | heap_dump(heapnode_t * top, int32 level) |
| | { |
| | int32 i; |
| |
|
| | if (!top) |
| | return; |
| |
|
| | for (i = 0; i < level; i++) |
| | printf(" "); |
| | |
| | heap_dump(top->l, level + 1); |
| | heap_dump(top->r, level + 1); |
| | } |
| | #endif |
| |
|
| |
|
| | heap_t * |
| | heap_new(void) |
| | { |
| | heap_t *h = ckd_calloc(1, sizeof(*h)); |
| | return h; |
| | } |
| |
|
| |
|
| | static heapnode_t * |
| | subheap_insert(heapnode_t * root, void *data, int32 val) |
| | { |
| | heapnode_t *h; |
| | void *tmpdata; |
| | int32 tmpval; |
| |
|
| | if (!root) { |
| | h = (heapnode_t *) ckd_calloc(1, sizeof(heapnode_t)); |
| | h->data = data; |
| | h->val = val; |
| | h->l = h->r = NULL; |
| | h->nl = h->nr = 0; |
| | return h; |
| | } |
| |
|
| | |
| | if (root->val > val) { |
| | tmpdata = root->data; |
| | tmpval = root->val; |
| | root->data = data; |
| | root->val = val; |
| | data = tmpdata; |
| | val = tmpval; |
| | } |
| |
|
| | |
| | if (root->nl > root->nr) { |
| | root->r = subheap_insert(root->r, data, val); |
| | root->nr++; |
| | } |
| | else { |
| | root->l = subheap_insert(root->l, data, val); |
| | root->nl++; |
| | } |
| |
|
| | return root; |
| | } |
| |
|
| |
|
| | int |
| | heap_insert(heap_t *heap, void *data, int32 val) |
| | { |
| | heap->top = subheap_insert(heap->top, data, val); |
| | return 0; |
| | } |
| |
|
| |
|
| | static heapnode_t * |
| | subheap_pop(heapnode_t * root) |
| | { |
| | heapnode_t *l, *r; |
| |
|
| | |
| | l = root->l; |
| | r = root->r; |
| |
|
| | if (!l) { |
| | if (!r) { |
| | ckd_free((char *) root); |
| | return NULL; |
| | } |
| | else { |
| | root->data = r->data; |
| | root->val = r->val; |
| | root->r = subheap_pop(r); |
| | root->nr--; |
| | } |
| | } |
| | else { |
| | if ((!r) || (l->val < r->val)) { |
| | root->data = l->data; |
| | root->val = l->val; |
| | root->l = subheap_pop(l); |
| | root->nl--; |
| | } |
| | else { |
| | root->data = r->data; |
| | root->val = r->val; |
| | root->r = subheap_pop(r); |
| | root->nr--; |
| | } |
| | } |
| |
|
| | return root; |
| | } |
| |
|
| |
|
| | int |
| | heap_pop(heap_t *heap, void **data, int32 * val) |
| | { |
| | if (heap->top == NULL) |
| | return 0; |
| | *data = heap->top->data; |
| | *val = heap->top->val; |
| | heap->top = subheap_pop(heap->top); |
| | return 1; |
| | } |
| |
|
| |
|
| | int |
| | heap_top(heap_t *heap, void **data, int32 * val) |
| | { |
| | if (heap->top == NULL) |
| | return 0; |
| | *data = heap->top->data; |
| | *val = heap->top->val; |
| | return 1; |
| | } |
| |
|
| | static int |
| | heap_remove_one(heap_t *heap, heapnode_t *top, void *data) |
| | { |
| | if (top == NULL) |
| | return -1; |
| | else if (top->data == data) { |
| | assert(top == heap->top); |
| | heap->top = subheap_pop(heap->top); |
| | return 0; |
| | } |
| | if (top->l) { |
| | if (top->l->data == data) { |
| | top->l = subheap_pop(top->l); |
| | --top->nl; |
| | return 0; |
| | } |
| | else if (heap_remove_one(heap, top->l, data) == 0) { |
| | --top->nl; |
| | return 0; |
| | } |
| | } |
| | if (top->r) { |
| | if (top->r->data == data) { |
| | top->r = subheap_pop(top->r); |
| | --top->nr; |
| | return 0; |
| | } |
| | else if (heap_remove_one(heap, top->r, data) == 0) { |
| | --top->nr; |
| | return 0; |
| | } |
| | } |
| | return -1; |
| | } |
| |
|
| | int |
| | heap_remove(heap_t *heap, void *data) |
| | { |
| | return heap_remove_one(heap, heap->top, data); |
| | } |
| |
|
| |
|
| | size_t |
| | heap_size(heap_t *heap) |
| | { |
| | if (heap->top == NULL) |
| | return 0; |
| | return heap->top->nl + heap->top->nr + 1; |
| | } |
| |
|
| | int |
| | heap_destroy(heap_t *heap) |
| | { |
| | void *data; |
| | int32 val; |
| |
|
| | |
| | while (heap_pop(heap, &data, &val) > 0) |
| | ; |
| | ckd_free(heap); |
| |
|
| | return 0; |
| | } |
| |
|