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.
|
The implementation is about 300 lines.
|
||||||
|
|
||||||
BSD 2-Clause license.
|
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_IMPL
|
||||||
#ifdef AATREE_ASSERT
|
#ifdef AATREE_ASSERT
|
||||||
# include <assert.h>
|
# include <assert.h>
|
||||||
|
# define aatree_assert assert
|
||||||
#else
|
#else
|
||||||
# define assert(e) (void)0
|
# define aatree_assert(e) (void)0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
static void aatree_relink(struct aatree *old, struct aatree *nw)
|
static void aatree_relink(struct aatree *old, struct aatree *nw)
|
||||||
{
|
{
|
||||||
assert(old);
|
aatree_assert(old);
|
||||||
|
|
||||||
if (old->parent) {
|
if (old->parent) {
|
||||||
if (old->parent->left == old)
|
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)
|
else if (old->parent->right == old)
|
||||||
old->parent->right = nw;
|
old->parent->right = nw;
|
||||||
else
|
else
|
||||||
assert(0);
|
aatree_assert(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -155,7 +156,7 @@ static struct aatree *aatree_split(struct aatree *t)
|
||||||
aatree_relink(A, t);
|
aatree_relink(A, t);
|
||||||
A->parent = t;
|
A->parent = t;
|
||||||
|
|
||||||
assert(t->level != UINT_MAX);
|
aatree_assert(t->level != UINT_MAX);
|
||||||
t->level += 1;
|
t->level += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -216,7 +217,7 @@ AATREE_PREFIX struct aatree *aatree_src(struct aatree *root,
|
||||||
{
|
{
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
assert(key);
|
aatree_assert(key);
|
||||||
|
|
||||||
while (root) {
|
while (root) {
|
||||||
c = cmp(key, root);
|
c = cmp(key, root);
|
||||||
|
@ -292,18 +293,18 @@ AATREE_PREFIX struct aatree *aatree_del(struct aatree *root,
|
||||||
if (root) for (;;) {
|
if (root) for (;;) {
|
||||||
if (aatree_lvl(root->left) < root->level - 1
|
if (aatree_lvl(root->left) < root->level - 1
|
||||||
|| aatree_lvl(root->right) < root->level - 1) {
|
|| aatree_lvl(root->right) < root->level - 1) {
|
||||||
assert(root->level != 0);
|
aatree_assert(root->level != 0);
|
||||||
root->level -= 1;
|
root->level -= 1;
|
||||||
|
|
||||||
if (aatree_lvl(root->right) > root->level) {
|
if (aatree_lvl(root->right) > root->level) {
|
||||||
assert(root->right);
|
aatree_assert(root->right);
|
||||||
root->right->level = root->level;
|
root->right->level = root->level;
|
||||||
}
|
}
|
||||||
|
|
||||||
root = aatree_skew(root);
|
root = aatree_skew(root);
|
||||||
root->right = aatree_skew(root->right);
|
root->right = aatree_skew(root->right);
|
||||||
|
|
||||||
assert(root->right);
|
aatree_assert(root->right);
|
||||||
root->right->right = aatree_skew(root->right->right);
|
root->right->right = aatree_skew(root->right->right);
|
||||||
|
|
||||||
root = aatree_split(root);
|
root = aatree_split(root);
|
||||||
|
@ -443,10 +444,12 @@ static void test_delete(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < NODE_NUM/2; i++) {
|
for (i = 0; i < NODE_NUM/2; i++) {
|
||||||
|
/*
|
||||||
printf("digraph t%d {", i);
|
printf("digraph t%d {", i);
|
||||||
aatree_print(root, tnp);
|
aatree_print(root, tnp);
|
||||||
printf("}\n");
|
printf("}\n");
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
|
*/
|
||||||
|
|
||||||
test_node.key = i;
|
test_node.key = i;
|
||||||
root = aatree_del(root, &test_node.node, &match, test_cmp);
|
root = aatree_del(root, &test_node.node, &match, test_cmp);
|
||||||
|
|
Loading…
Reference in New Issue