diff --git a/README.rst b/README.rst index 3cdccb8..4a98dc8 100644 --- a/README.rst +++ b/README.rst @@ -1,5 +1,67 @@ -Intrusive, single file, imperative AA tree. +Intrusive, single file, imperative AA tree that works on freestanding +systems. The implementation is about 300 lines. BSD 2-Clause license. + +------------------ +What are AA Trees? +------------------ + +`AA Trees `_ are a type of +self-balancing binary tree. Unlike AVL trees or red-black trees, which +store a constant amount of information per node, AA trees store the +"level" of a node (which is approximately the height of the node from +the bottom of the tree). This makes rebalancing operations much simpler: +most of the code in this library is for handling standard binary tree +operations. + +Theoretically, this limits the size of the binary tree to +``2**(2**16-1)`` nodes, which is no problem in practice. + +This implementation is "intrusive", meaning that the node data structure +does not contain the key or value stored in it. You need to define your +own structure and search function like :: + + struct node { + char *key; + void *val; + struct aatree node; + }; + + int node_cmp(struct aatree *a1, struct aatree *a2) + { + struct node *n1 = (void *)((char *)a1 - offsetof(struct node, node)); + struct node *n2 = (void *)((char *)a2 - offsetof(struct node, node)); + + return strcmp(n1->key, n2->key); + } + +This is standard, portable C99. + +----------------- +Using the Library +----------------- + +In *one* C file, do the following :: + + /* Optional declarations: */ + #define AATREE_PREFIX /* prefix of each function: put "declspec" or + "static" here */ + #define AATREE_ASSERT /* Define this if you want the code to have + asserts. Do not define if you do not want + standard library asserts. */ + + /* Mandatory declarations */ + #define AATREE_IMPL + #include "aatree.h" + +This will include the implementation of the functions into the C file. +If your project consists of more than one C file, then all you need to +do is ``#include aatree.h``. The linker will take care of everything else. + +The library also includes it own test code for convienence. Define +``AATREE_TEST`` to turn the header into a self-contained C file with a +``main()`` function. See ``Makefile`` for an example of compiling the +test. diff --git a/aatree.h b/aatree.h index 0377684..10c9f0c 100644 --- a/aatree.h +++ b/aatree.h @@ -61,15 +61,16 @@ static void aatree_init(struct aatree *t) #ifdef AATREE_IMPL #ifdef AATREE_ASSERT # include +# define aatree_assert assert #else -# define assert(e) (void)0 +# define aatree_assert(e) (void)0 #endif #include #include static void aatree_relink(struct aatree *old, struct aatree *nw) { - assert(old); + aatree_assert(old); if (old->parent) { if (old->parent->left == old) @@ -77,7 +78,7 @@ static void aatree_relink(struct aatree *old, struct aatree *nw) else if (old->parent->right == old) old->parent->right = nw; else - assert(0); + aatree_assert(0); } } @@ -155,7 +156,7 @@ static struct aatree *aatree_split(struct aatree *t) aatree_relink(A, t); A->parent = t; - assert(t->level != UINT_MAX); + aatree_assert(t->level != UINT_MAX); t->level += 1; } @@ -216,7 +217,7 @@ AATREE_PREFIX struct aatree *aatree_src(struct aatree *root, { int c; - assert(key); + aatree_assert(key); while (root) { c = cmp(key, root); @@ -292,18 +293,18 @@ AATREE_PREFIX struct aatree *aatree_del(struct aatree *root, if (root) for (;;) { if (aatree_lvl(root->left) < root->level - 1 || aatree_lvl(root->right) < root->level - 1) { - assert(root->level != 0); + aatree_assert(root->level != 0); root->level -= 1; if (aatree_lvl(root->right) > root->level) { - assert(root->right); + aatree_assert(root->right); root->right->level = root->level; } root = aatree_skew(root); root->right = aatree_skew(root->right); - assert(root->right); + aatree_assert(root->right); root->right->right = aatree_skew(root->right->right); root = aatree_split(root); @@ -443,10 +444,12 @@ static void test_delete(void) } for (i = 0; i < NODE_NUM/2; i++) { + /* printf("digraph t%d {", i); aatree_print(root, tnp); printf("}\n"); fflush(stdout); + */ test_node.key = i; root = aatree_del(root, &test_node.node, &match, test_cmp);