-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
0a54548
commit 5341d0e
Showing
10 changed files
with
430 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
#include <assert.h> | ||
#include <stdint.h> | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <string.h> | ||
#include <unistd.h> | ||
|
||
#include "heap.h" | ||
|
||
bool u32_leq(void *a, void *b) { | ||
return *(uint32_t*)a <= *(uint32_t*)b; | ||
} | ||
|
||
void u32_cpy(void *a, void *b) { | ||
*(uint32_t*)a = *(uint32_t*)b; | ||
} | ||
|
||
void test_heap_test_1(void) { | ||
|
||
char heap_mem[heap_mem_size(16, sizeof(uint32_t))]; | ||
struct heap *h = heap_create( heap_mem | ||
, sizeof(heap_mem) | ||
, sizeof(uint32_t) | ||
, u32_leq | ||
, u32_cpy ); | ||
|
||
fprintf(stdout, "# heap_size: %ld\n", heap_size(h)); | ||
fprintf(stdout, "# heap_empty: %s\n", heap_empty(h) ? "yes" : "no"); | ||
|
||
uint32_t vs[] = {9,100,7,2,5,200,1,20,8,8,8,150}; | ||
size_t i = 0; | ||
for(; i < sizeof(vs)/sizeof(vs[0]); i++ ) { | ||
if( !heap_add(h, &vs[i]) ) { | ||
break; | ||
} | ||
} | ||
|
||
fprintf(stdout, "# heap_empty: %s\n", heap_empty(h) ? "yes" : "no"); | ||
|
||
while( !heap_empty(h) ) { | ||
uint32_t *mp = heap_pop(h); | ||
if( !mp ) | ||
break; | ||
fprintf(stdout, "# %d\n", *mp); | ||
} | ||
} | ||
|
||
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_2(void) { | ||
|
||
char heap_mem[heap_mem_size(10, sizeof(uint32_t))]; | ||
struct heap *h = heap_create( heap_mem | ||
, sizeof(heap_mem) | ||
, sizeof(uint32_t) | ||
, u32_leq | ||
, u32_cpy ); | ||
|
||
fprintf(stdout, "# heap_size: %ld\n", heap_size(h)); | ||
|
||
size_t N = 3000; | ||
|
||
size_t n = 0; | ||
for(n = N; n; n-- ) { | ||
__test_head_add_gt(h, n); | ||
} | ||
|
||
fprintf(stdout, "\n"); | ||
while( !heap_empty(h) ) { | ||
uint32_t *mp = heap_pop(h); | ||
if( !mp ) | ||
break; | ||
fprintf(stdout, "# %d\n", *mp); | ||
} | ||
|
||
for(n = 0; n <= N; n++ ) { | ||
__test_head_add_gt(h, n); | ||
} | ||
|
||
fprintf(stdout, "\n"); | ||
while( !heap_empty(h) ) { | ||
uint32_t *mp = heap_pop(h); | ||
if( !mp ) | ||
break; | ||
fprintf(stdout, "# %d\n", *mp); | ||
} | ||
} | ||
|
||
struct cw { | ||
uint16_t cat; | ||
uint32_t weight; | ||
} __attribute__ ((aligned)); | ||
|
||
static bool __cw_leq(void *a_, void *b_) { | ||
struct cw *a = a_; | ||
struct cw *b = b_; | ||
return a->weight <= b->weight; | ||
} | ||
|
||
static void __cw_cpy(void *a, void *b) { | ||
memcpy(a, b, sizeof(struct cw)); | ||
} | ||
|
||
void test_heap_test_3(void) { | ||
|
||
char heap_mem[heap_mem_size(5, sizeof(struct cw))]; | ||
struct heap *h = heap_create( heap_mem | ||
, sizeof(heap_mem) | ||
, sizeof(struct cw) | ||
, __cw_leq | ||
, __cw_cpy ); | ||
|
||
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, "\n"); | ||
while( !heap_empty(h) ) { | ||
struct cw *c = heap_pop(h); | ||
fprintf(stdout, "# {%d, %d}\n", c->cat, c->weight); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
#ifndef __heap_h | ||
#define __heap_h | ||
|
||
#include <stddef.h> | ||
#include <stdbool.h> | ||
|
||
struct heap; | ||
|
||
// FIXED SIZE BINARY HEAP | ||
|
||
struct heap * heap_create( void *mem | ||
, size_t memsize | ||
, size_t item_size | ||
, bool (*item_leq)(void*,void*) | ||
, void (*item_cpy)(void*,void*) | ||
); | ||
|
||
size_t heap_mem_size(size_t n, size_t chunk_size); | ||
size_t heap_size(struct heap*); | ||
bool heap_full(struct heap*); | ||
bool heap_empty(struct heap*); | ||
bool heap_add(struct heap *, void *); | ||
void *heap_get(struct heap*); | ||
void *heap_pop(struct heap*); | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
#include <string.h> | ||
#include <stdint.h> | ||
#include "heap.h" | ||
|
||
struct heap { | ||
size_t n; | ||
size_t size; | ||
size_t item_size; | ||
bool (*leq)(void*,void*); | ||
void (*cpy)(void*,void*); | ||
char data[0]; | ||
}; | ||
|
||
struct heap *heap_create( void *mem | ||
, size_t memsize | ||
, size_t item_size | ||
, bool (*item_leq)(void*,void*) | ||
, void (*item_cpy)(void*,void*) | ||
) { | ||
|
||
const size_t headsz = sizeof(struct heap); | ||
const size_t minsz = 3*item_size + headsz; | ||
|
||
if( memsize < minsz ) { | ||
return 0; | ||
} | ||
|
||
struct heap *h = mem; | ||
h->n = 0; | ||
h->size = (memsize - headsz) / item_size; | ||
h->item_size = item_size; | ||
h->leq = item_leq; | ||
h->cpy = item_cpy; | ||
|
||
return h; | ||
} | ||
|
||
static inline size_t L(size_t i) { | ||
return (i*2 + 1); | ||
} | ||
|
||
static inline size_t R(size_t i) { | ||
return (i*2 + 2); | ||
} | ||
|
||
static inline size_t P(size_t i) { | ||
return (i-1)/2; | ||
} | ||
|
||
static inline void* pitem(struct heap *h, size_t i) { | ||
return &h->data[i*h->item_size]; | ||
} | ||
|
||
static inline void swap(struct heap *h, size_t i, size_t j) { | ||
char tmp[h->item_size]; | ||
|
||
void *pi = pitem(h, i); | ||
void *pj = pitem(h, j); | ||
|
||
h->cpy(tmp, pi); | ||
h->cpy(pi, pj); | ||
h->cpy(pj, tmp); | ||
} | ||
|
||
static inline bool leq(struct heap *h, size_t i, size_t j) { | ||
return h->leq(pitem(h,i), pitem(h,j)); | ||
} | ||
|
||
static void sift_down(struct heap *h, size_t i) { | ||
while( L(i) < h->n ) { | ||
size_t l = L(i); | ||
size_t r = R(i); | ||
size_t j = l; | ||
if( r < h->n && leq(h, r, l) ) { | ||
j = r; | ||
} | ||
if( leq(h, i, j) ) { | ||
break; | ||
} | ||
swap(h, i, j); | ||
i = j; | ||
} | ||
} | ||
|
||
static void sift_up(struct heap *h, size_t i) { | ||
for(; i && leq(h, i, P(i)); i = P(i) ) { | ||
swap(h, i, P(i)); | ||
} | ||
} | ||
|
||
size_t heap_size(struct heap *h) { | ||
return h->size; | ||
} | ||
|
||
size_t heap_mem_size(size_t n, size_t chunk_size) { | ||
return (sizeof(struct heap) + n*chunk_size); | ||
} | ||
|
||
bool heap_empty(struct heap *h) { | ||
return (0 == h->n); | ||
} | ||
|
||
bool heap_full(struct heap* h) { | ||
return h->n == h->size; | ||
} | ||
|
||
bool heap_add(struct heap *h, void *v) { | ||
if( h->n >= h->size ) { | ||
return false; | ||
} | ||
|
||
size_t i = h->n++; | ||
|
||
h->cpy(pitem(h,i), v); | ||
sift_up(h, i); | ||
|
||
return true; | ||
} | ||
|
||
void *heap_get(struct heap *h) { | ||
|
||
if( !h->n ) { | ||
return 0; | ||
} | ||
|
||
return pitem(h, 0); | ||
} | ||
|
||
void *heap_pop(struct heap *h) { | ||
|
||
if( !h->n ) { | ||
return 0; | ||
} | ||
|
||
if( h->n == 1 ) { | ||
h->n--; | ||
return pitem(h, 0); | ||
} | ||
|
||
size_t l = --h->n; | ||
swap(h, 0, l); | ||
sift_down(h, 0); | ||
|
||
return pitem(h, l); | ||
} | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
??? hash create succeed | ||
??? hash items added: 14 | ||
??? 0 1000 | ||
??? 1 1001 | ||
??? 2 1002 | ||
??? 3 1003 | ||
??? 4 1004 | ||
??? 5 1005 | ||
??? 6 1006 | ||
??? 7 1007 | ||
??? 8 1008 | ||
??? 9 1009 | ||
??? 10 1010 | ||
??? 11 1011 | ||
??? 12 1012 | ||
??? 13 1013 | ||
extra items added: 10000 | ||
extra items removed | ||
??? 0 1000 | ||
??? 1 1001 | ||
??? 2 1002 | ||
??? 3 1003 | ||
??? 4 1004 | ||
??? 5 1005 | ||
??? 6 1006 | ||
??? 7 1007 | ||
??? 8 1008 | ||
??? 9 1009 | ||
??? 10 1010 | ||
??? 11 1011 | ||
??? 12 1012 | ||
??? 13 1013 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
dummy0 | ||
dummy2 14! | ||
dummy2 88! |
Oops, something went wrong.