5 /* AA Tree, which came from Arne Andersson
6 * Balanced Search Trees Made Simple
7 * https://user.it.uu.se/~arnea/ps/simp.pdf
9 * As fast as an RB-tree, but free of those
10 * ugly special cases. */
15 struct map_pair *pair;
16 struct tm_node *left, *right;
21 struct tm_node *root, *bottom;
22 struct tm_node *deleted, *last;
32 tm_new(comparator *cmp, void *cmp_aux)
34 treemap *t = malloc(sizeof *t);
35 struct tm_node *bottom = malloc(sizeof *bottom);
42 /* sentinel living below all leaves */
43 *bottom = (struct tm_node){
44 .left = bottom, .right = bottom, .level = 0
62 tm_dtor(treemap *t, dtor *key_dtor, dtor *val_dtor, void *dtor_aux)
66 t->key_dtor = key_dtor;
67 t->val_dtor = val_dtor;
68 t->dtor_aux = dtor_aux;
72 _tm_length(const struct tm_node *n, const struct tm_node *bottom)
77 _tm_length(n->left, bottom) + _tm_length(n->right, bottom);
81 tm_length(const treemap *t)
83 return t ? _tm_length(t->root, t->bottom) : 0;
87 tm_is_empty(const treemap *t)
89 return tm_length(t) == 0;
93 _tm_at(const treemap *t, const struct tm_node *n, const void *key)
97 int x = t->cmp(n->pair->k, key, t->cmp_aux);
101 return _tm_at(t, n->left, key);
102 return _tm_at(t, n->right, key);
106 tm_at(const treemap *t, const void *key)
108 return t ? _tm_at(t, t->root, key) : NULL;
111 static struct tm_node *
112 _tm_skew(struct tm_node *n) {
113 if (n->level != n->left->level)
115 struct tm_node *left = n->left;
116 n->left = left->right;
122 static struct tm_node *
123 _tm_split(struct tm_node *n) {
124 if(n->right->right->level != n->level)
126 struct tm_node *right = n->right;
127 n->right = right->left;
134 static struct tm_node *
135 _tm_insert(treemap *t, struct tm_node *n, struct tm_node *prealloc)
139 int x = t->cmp(n->pair->k, prealloc->pair->k, t->cmp_aux);
141 n->left = _tm_insert(t, n->left, prealloc);
143 n->right = _tm_insert(t, n->right, prealloc);
146 // TODO: free the right stuff in prealloc
149 return _tm_split(_tm_skew(n));
153 tm_insert(treemap *t, void *key, void *val)
157 /* attempt the malloc before potentially splitting
158 * and skewing the tree, so the insertion can be a
159 * no-op on failure */
160 struct tm_node *prealloc = malloc(sizeof *prealloc);
161 struct map_pair *p = malloc(sizeof *p);
168 *p = (struct map_pair){.k = key, .v = val};
169 *prealloc = (struct tm_node){
170 .level = 1, .pair = p, .left = t->bottom, .right = t->bottom
173 return _tm_insert(t, t->root, prealloc);
177 tm_remove(treemap *t, void *key)