static int hnode_up(gh_heap_t *heap, gh_hnode_t *hnode) { unsigned int cur_idx = hnode->index; gh_hnode_t **cur_ptr = hnode_ptr(heap, cur_idx); unsigned int parent_idx; gh_hnode_t **parent_ptr; int action = 0; assert(*cur_ptr == hnode); while (cur_idx > 0) { parent_idx = (cur_idx - 1) >> 1; parent_ptr = hnode_ptr(heap, parent_idx); assert((*parent_ptr)->index == parent_idx); if (heap->cmp_op(*parent_ptr, hnode)) break; (*parent_ptr)->index = cur_idx; *cur_ptr = *parent_ptr; cur_ptr = parent_ptr; cur_idx = parent_idx; action = 1; } hnode->index = cur_idx; *cur_ptr = hnode; return action; }
int gh_heap_remove(gh_heap_t *heap, gh_hnode_t *hnode) { unsigned int count = heap->count; unsigned int cur_idx = hnode->index; gh_hnode_t **cur_ptr; gh_hnode_t *last; assert(gh_hnode_is_valid(hnode)); assert(cur_idx < count); cur_ptr = hnode_ptr(heap, cur_idx); assert(*cur_ptr == hnode); count--; last = *hnode_ptr(heap, count); heap->count = count; if (last == hnode) return 0; last->index = cur_idx; *cur_ptr = last; if (!hnode_up(heap, *cur_ptr)) hnode_down(heap, *cur_ptr); gh_hnode_invalidate(hnode); return 0; }
static int hnode_down(gh_heap_t *heap, gh_hnode_t *hnode) { unsigned int count = heap->count; unsigned int ch1_idx, ch2_idx, cur_idx; gh_hnode_t **ch1_ptr, **ch2_ptr, **cur_ptr; gh_hnode_t *ch1, *ch2; int action = 0; cur_idx = hnode->index; cur_ptr = hnode_ptr(heap, cur_idx); assert(*cur_ptr == hnode); while (cur_idx < count) { ch1_idx = (cur_idx << 1) + 1; if (ch1_idx >= count) break; ch1_ptr = hnode_ptr(heap, ch1_idx); ch1 = *ch1_ptr; ch2_idx = ch1_idx + 1; if (ch2_idx < count) { ch2_ptr = hnode_ptr(heap, ch2_idx); ch2 = *ch2_ptr; if (heap->cmp_op(ch2, ch1)) { ch1_idx = ch2_idx; ch1_ptr = ch2_ptr; ch1 = ch2; } } assert(ch1->index == ch1_idx); if (heap->cmp_op(hnode, ch1)) break; ch1->index = cur_idx; *cur_ptr = ch1; cur_ptr = ch1_ptr; cur_idx = ch1_idx; action = 1; } hnode->index = cur_idx; *cur_ptr = hnode; return action; }
int gh_heap_push(gh_heap_t *heap, gh_hnode_t *hnode) { gh_hnode_t **new_ptr; unsigned int new_index = heap->count; assert(!gh_hnode_is_valid(hnode)); if (new_index == heap->highwm) heap_grow(heap); hnode->index = new_index; new_ptr = hnode_ptr(heap, new_index); heap->count++; *new_ptr = hnode; hnode_up(heap, hnode); return 0; }
gh_hnode_t *gh_heap_find(gh_heap_t *heap, unsigned int index) { if (index >= heap->count) return NULL; return *hnode_ptr(heap, index); }