documentation
This commit is contained in:
parent
45af932762
commit
91640931d9
64
README.rst
64
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 <https://user.it.uu.se/~arneande/ps/simp.pdf>`_ 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.
|
||||
|
|
19
aatree.h
19
aatree.h
|
@ -61,15 +61,16 @@ static void aatree_init(struct aatree *t)
|
|||
#ifdef AATREE_IMPL
|
||||
#ifdef AATREE_ASSERT
|
||||
# include <assert.h>
|
||||
# define aatree_assert assert
|
||||
#else
|
||||
# define assert(e) (void)0
|
||||
# define aatree_assert(e) (void)0
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
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);
|
||||
|
|
Loading…
Reference in New Issue