quicklists can be used as a set of pointers (this will be useful).

This commit is contained in:
Enno Rehling 2011-02-24 22:27:04 -08:00
parent 372908a9af
commit a538c52bc4
3 changed files with 65 additions and 4 deletions

View File

@ -29,7 +29,7 @@ struct quicklist {
}; };
void * ql_get(quicklist * ql, int index) { void * ql_get(const quicklist * ql, int index) {
return (ql && index<ql->num_elements)?ql->elements[index]:ql_get(ql->next, index-ql->num_elements); return (ql && index<ql->num_elements)?ql->elements[index]:ql_get(ql->next, index-ql->num_elements);
} }
@ -43,7 +43,7 @@ void ql_push(quicklist ** qlp, void * data) {
qlp = &(*qlp)->next; qlp = &(*qlp)->next;
} }
if (!*qlp) { if (!*qlp) {
ql = malloc(sizeof(quicklist)); ql = (quicklist *)malloc(sizeof(quicklist));
ql->num_elements = 0; ql->num_elements = 0;
ql->next = 0; ql->next = 0;
*qlp = ql; *qlp = ql;
@ -94,7 +94,7 @@ int ql_insert(quicklist ** qlp, int index, void * data) {
ql->elements[index]=data; ql->elements[index]=data;
++ql->num_elements; ++ql->num_elements;
} else { } else {
quicklist * qn = malloc(sizeof(quicklist)); quicklist * qn = (quicklist *)malloc(sizeof(quicklist));
qn->next = ql->next; qn->next = ql->next;
ql->next = qn; ql->next = qn;
qn->num_elements = QL_LIMIT; qn->num_elements = QL_LIMIT;
@ -145,3 +145,32 @@ void ql_free(struct quicklist * ql)
if (ql->next) ql_free(ql->next); if (ql->next) ql_free(ql->next);
free(ql); free(ql);
} }
int ql_set_insert(struct quicklist ** qlp, void * data)
{
if (*qlp) {
quicklist * ql = *qlp;
if (ql->num_elements>0 && ql->elements[ql->num_elements-1] < data) {
if (ql->num_elements==QL_MAXSIZE || (ql->next && ql->next->elements[0]<=data)) {
return ql_set_insert(&ql->next, data);
} else {
ql->elements[ql->num_elements++] = data;
}
return 0;
} else {
int i;
/* TODO: OPT | binary search */
for (i=0;i!=ql->num_elements;++i) {
if (data < ql->elements[i]) {
ql_insert(qlp, i, data);
return 0;
}
if (data == ql->elements[i]) {
return 1;
}
}
}
}
ql_push(qlp, data);
return 0;
}

View File

@ -23,7 +23,7 @@ extern "C" {
/* see http://en.wikipedia.org/wiki/Unrolled_linked_list */ /* see http://en.wikipedia.org/wiki/Unrolled_linked_list */
typedef struct quicklist quicklist; typedef struct quicklist quicklist;
void * ql_get(struct quicklist * ql, int index); void * ql_get(const struct quicklist * ql, int index);
int ql_length(const struct quicklist * ql); int ql_length(const struct quicklist * ql);
void ql_push(struct quicklist ** qlp, void * data); void ql_push(struct quicklist ** qlp, void * data);
int ql_delete(struct quicklist ** qlp, int index); int ql_delete(struct quicklist ** qlp, int index);
@ -31,6 +31,9 @@ int ql_insert(struct quicklist ** qlp, int index, void * data);
void ql_foreach(struct quicklist * ql, void (*cb)(void *)); void ql_foreach(struct quicklist * ql, void (*cb)(void *));
int ql_advance(struct quicklist ** iterator, int * index, int stride); int ql_advance(struct quicklist ** iterator, int * index, int stride);
void ql_free(struct quicklist * ql); void ql_free(struct quicklist * ql);
/* you can use it as a set (sorted pointers)*/
int ql_set_insert(struct quicklist ** qlp, void * data);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -17,6 +17,33 @@ static void test_insert(CuTest * tc) {
} }
} }
static void test_insert_delete_gives_null(CuTest * tc) {
struct quicklist * ql = NULL;
ql_push(&ql, (void*)42);
ql_delete(&ql, 0);
CuAssertPtrEquals(tc, 0, ql);
}
static void test_set_insert(CuTest * tc) {
struct quicklist * ql = NULL;
int a;
a = ql_set_insert(&ql, (void*)42);
CuAssertIntEquals(tc, 1, ql_length(ql));
CuAssertIntEquals(tc, 0, a);
a = ql_set_insert(&ql, (void*)43);
CuAssertIntEquals(tc, 2, ql_length(ql));
CuAssertIntEquals(tc, 0, a);
a = ql_set_insert(&ql, (void*)42);
CuAssertIntEquals(tc, 2, ql_length(ql));
CuAssertIntEquals(tc, 1, a);
a = ql_set_insert(&ql, (void*)41);
CuAssertIntEquals(tc, 0, a);
CuAssertIntEquals(tc, 3, ql_length(ql));
CuAssertIntEquals(tc, 41, (int)ql_get(ql, 0));
CuAssertIntEquals(tc, 42, (int)ql_get(ql, 1));
CuAssertIntEquals(tc, 43, (int)ql_get(ql, 2));
}
static void test_advance(CuTest * tc) { static void test_advance(CuTest * tc) {
struct quicklist * ql = NULL, *qli; struct quicklist * ql = NULL, *qli;
int i, n = 31; int i, n = 31;
@ -84,8 +111,10 @@ CuSuite* get_quicklist_suite(void)
SUITE_ADD_TEST(suite, test_advance); SUITE_ADD_TEST(suite, test_advance);
SUITE_ADD_TEST(suite, test_push); SUITE_ADD_TEST(suite, test_push);
SUITE_ADD_TEST(suite, test_insert); SUITE_ADD_TEST(suite, test_insert);
SUITE_ADD_TEST(suite, test_insert_delete_gives_null);
SUITE_ADD_TEST(suite, test_insert_many); SUITE_ADD_TEST(suite, test_insert_many);
SUITE_ADD_TEST(suite, test_delete_rand); SUITE_ADD_TEST(suite, test_delete_rand);
SUITE_ADD_TEST(suite, test_delete_edgecases); SUITE_ADD_TEST(suite, test_delete_edgecases);
SUITE_ADD_TEST(suite, test_set_insert);
return suite; return suite;
} }