int heap_insert(struct heap *h, struct heapitem *item) { unsigned int i, parent; if (heap_full(h)) { if (heap_increase_size(h, HEAP_DEFAULT_INCREASE_SIZE)) { return -1; } } i = h->size; parent = (i - 1) / 2; /* find the correct place to insert */ while ((i > 0) && h->cmp(item, h->map[parent])) { h->map[i] = h->map[parent]; h->map[i]->index = i; i = parent; parent = (i - 1) / 2; } h->map[i] = item; item->index = i; h->size++; item->active = 1; return 0; }
static void __test_head_add_gt(struct heap *h, uint32_t v) { if( !heap_full(h) ) { heap_add(h, &v); } else { uint32_t *min = heap_get(h); if( *min < v ) { heap_pop(h); heap_add(h, &v); } } }
void test_heap_test_4(void) { size_t memsize = heap_mem_size(1, sizeof(struct cw)); fprintf(stderr, "memsize: %ld\n", memsize); char heap_mem[heap_mem_size(1, sizeof(struct cw))]; struct heap *h = heap_create( heap_mem , sizeof(heap_mem) , sizeof(struct cw) , __cw_leq , __cw_cpy ); fprintf(stderr, "heap: %p\n", h); fprintf(stdout, "# heap_size: %ld\n", heap_size(h)); struct cw cats[] = { { 1, 1 } , { 2, 1 } , { 1, 2 } , { 3, 1 } , { 12, 3 } , { 5, 1 } , { 31, 2 } , { 6, 2 } , { 7, 1 } , { 7, 1 } , { 10, 5 } }; fprintf(stdout, "\n"); size_t i = 0; for(; i < sizeof(cats)/sizeof(cats[0]); i++ ) { fprintf(stdout, "# {%d, %d}\n", cats[i].cat, cats[i].weight); if( heap_full(h) ) { struct cw *min = heap_get(h); if( __cw_leq(min, &cats[i]) ) { heap_pop(h); } } heap_add(h, &cats[i]); } fprintf(stdout, "\nheap_items %ld\n", heap_items(h)); fprintf(stdout, "\n"); while( !heap_empty(h) ) { struct cw *c = heap_pop(h); fprintf(stdout, "# {%d, %d}\n", c->cat, c->weight); } }
static void invalidate_buckets_lru(struct cache *ca) { struct bucket *b; ssize_t i; ca->heap.used = 0; for_each_bucket(b, ca) { /* * If we fill up the unused list, if we then return before * adding anything to the free_inc list we'll skip writing * prios/gens and just go back to allocating from the unused * list: */ if (fifo_full(&ca->unused)) return; if (!can_invalidate_bucket(ca, b)) continue; if (!GC_SECTORS_USED(b) && bch_bucket_add_unused(ca, b)) continue; if (!heap_full(&ca->heap)) heap_add(&ca->heap, b, bucket_max_cmp); else if (bucket_max_cmp(b, heap_peek(&ca->heap))) { ca->heap.data[0] = b; heap_sift(&ca->heap, 0, bucket_max_cmp); } } for (i = ca->heap.used / 2 - 1; i >= 0; --i) heap_sift(&ca->heap, i, bucket_min_cmp); while (!fifo_full(&ca->free_inc)) { if (!heap_pop(&ca->heap, b, bucket_min_cmp)) { /* * We don't want to be calling invalidate_buckets() * multiple times when it can't do anything */ ca->invalidate_needs_gc = 1; wake_up_gc(ca->set); return; } invalidate_one_bucket(ca, b); } }
void heap_add(heap H, elem x) { REQUIRES(is_heap(H) && !heap_full(H)); int i = H->next; H->data[H->next] = x; H->next++; // Sift up takes O(log n) time while (i > 1) { ASSERT(1 <= i && i < H->next); ASSERT(is_heap_except_up(H, i)); ASSERT(grandparent_check(H, i)); if (ok_above(H, i/2, i)) { return; } swap_up(H, i); i = i/2; } ENSURES(is_heap(H)); }
static void invalidate_buckets_lru(struct cache *ca) { struct bucket *b; ssize_t i; ca->heap.used = 0; for_each_bucket(b, ca) { if (!bch_can_invalidate_bucket(ca, b)) continue; if (!heap_full(&ca->heap)) heap_add(&ca->heap, b, bucket_max_cmp); else if (bucket_max_cmp(b, heap_peek(&ca->heap))) { ca->heap.data[0] = b; heap_sift(&ca->heap, 0, bucket_max_cmp); } } for (i = ca->heap.used / 2 - 1; i >= 0; --i) heap_sift(&ca->heap, i, bucket_min_cmp); while (!fifo_full(&ca->free_inc)) { if (!heap_pop(&ca->heap, b, bucket_min_cmp)) { /* * We don't want to be calling invalidate_buckets() * multiple times when it can't do anything */ ca->invalidate_needs_gc = 1; wake_up_gc(ca->set); return; } bch_invalidate_one_bucket(ca, b); } }
int main(void) { uint32_t cnt, i, data[] = {14, 2, 22, 13, 23, 10, 90, 36, 108, 12, 9, 91, 1, 51, 11, 3, 15, 80, 3, 78, 53, 5, 12, 21, 65, 70, 4}; const uint32_t data_len = sizeof(data)/sizeof(uint32_t); struct heap heap = heap_create(data_len + 5); printf(COL_BEG "push data...\n" COL_END); for (i = 0; i < data_len; i++) if (!heap_full(&heap)) heap_push(&heap, &data[i]); printf("data len = %u, heap size = %u.\n", data_len, heap_size(&heap)); printf(COL_BEG "heap tree:\n" COL_END); heap_print_tr(&heap, &test_print); printf(COL_BEG "heap array:\n" COL_END); heap_print_arr(&heap, &test_print); heap_set_callbk(&heap, &test_less_than); printf(COL_BEG "after heapify:\n" COL_END); minheap_heapify(&heap); heap_print_tr(&heap, &test_print); cnt = 0; printf(COL_BEG "ranking emulation...:\n" COL_END); while (cnt < 100) { i = (i + 1) % data_len; if (!heap_full(&heap)) { printf("insert %d\n", data[i]); minheap_insert(&heap, &data[i]); } else { void *top = heap_top(&heap); if (test_less_than(top, &data[i])) { printf("replace with %d\n", data[i]); minheap_delete(&heap, 0); minheap_insert(&heap, &data[i]); } } cnt ++; } printf(COL_BEG "a heavy heap tree now:\n" COL_END); heap_print_tr(&heap, &test_print); minheap_sort(&heap); printf(COL_BEG "heap array after min-heap sort:\n" COL_END); heap_print_arr(&heap, &test_print); heap_destory(&heap); printf(COL_BEG "a new heap...\n" COL_END); heap = heap_create(data_len + 5); heap_set_callbk(&heap, &test_less_than); for (i = 0; i < data_len; i++) if (!heap_full(&heap)) heap_push(&heap, &data[i]); printf(COL_BEG "heap array:\n" COL_END); heap_print_arr(&heap, &test_print); heap_sort_desc(&heap); printf(COL_BEG "heap array after heap sort:\n" COL_END); heap_print_arr(&heap, &test_print); heap_print_tr(&heap, &test_print); heap_destory(&heap); printf(COL_BEG "sort a heap with one element...\n" COL_END); heap = heap_create(data_len + 5); heap_set_callbk(&heap, &test_less_than); heap_push(&heap, &data[0]); heap_print_tr(&heap, &test_print); heap_sort_desc(&heap); heap_destory(&heap); return 0; }