documentation

This commit is contained in:
Peter McGoron 2024-04-26 07:54:38 -04:00
parent 45af932762
commit 91640931d9
2 changed files with 74 additions and 9 deletions

View File

@ -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.

View File

@ -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);