2 #include "derp/treemap.h"
6 /* AA (Arne Andersson) Tree:
7 * Balanced Search Trees Made Simple
8 * https://user.it.uu.se/~arnea/ps/simp.pdf
10 * As fast as an RB-tree, but free of those
11 * ugly special cases. */
16 struct map_pair *pair;
17 struct tm_node *left, *right;
22 struct tm_node *root, *bottom;
23 struct tm_node *deleted, *last;
35 struct tm_node *n, *bottom;
39 tm_new(comparator *cmp, void *cmp_aux)
41 treemap *t = malloc(sizeof *t);
42 struct tm_node *bottom = malloc(sizeof *bottom);
49 /* sentinel living below all leaves */
50 *bottom = (struct tm_node){
51 .left = bottom, .right = bottom, .level = 0
75 tm_dtor(treemap *t, dtor *key_dtor, dtor *val_dtor, void *dtor_aux)
79 t->key_dtor = key_dtor;
80 t->val_dtor = val_dtor;
81 t->dtor_aux = dtor_aux;
85 internal_tm_length(const struct tm_node *n,
86 const struct tm_node *bottom)
91 internal_tm_length(n->left, bottom) +
92 internal_tm_length(n->right, bottom);
96 tm_length(const treemap *t)
98 return t ? internal_tm_length(t->root, t->bottom) : 0;
102 tm_is_empty(const treemap *t)
104 return tm_length(t) == 0;
108 internal_tm_at(const treemap *t, const struct tm_node *n,
113 int x = t->cmp(key, n->pair->k, t->cmp_aux);
117 return internal_tm_at(t, n->left, key);
118 return internal_tm_at(t, n->right, key);
122 tm_at(const treemap *t, const void *key)
124 return t ? internal_tm_at(t, t->root, key) : NULL;
127 static struct tm_node *
128 internal_tm_skew(struct tm_node *n) {
129 if (n->level != n->left->level)
131 struct tm_node *left = n->left;
132 n->left = left->right;
138 static struct tm_node *
139 internal_tm_split(struct tm_node *n) {
140 if(n->right->right->level != n->level)
142 struct tm_node *right = n->right;
143 n->right = right->left;
150 static struct tm_node *
151 internal_tm_insert(treemap *t, struct tm_node *n,
152 struct tm_node *prealloc)
156 int x = t->cmp(prealloc->pair->k, n->pair->k, t->cmp_aux);
158 n->left = internal_tm_insert(t, n->left, prealloc);
160 n->right = internal_tm_insert(t, n->right, prealloc);
163 /* prealloc was for naught, but we'll use its value */
164 if (n->pair->v != prealloc->pair->v && t->val_dtor)
165 t->val_dtor(n->pair->v, t->dtor_aux);
166 if (n->pair->k != prealloc->pair->k && t->key_dtor)
167 t->key_dtor(n->pair->k, t->dtor_aux);
168 *n->pair = *prealloc->pair;
169 free(prealloc->pair);
173 return internal_tm_split(internal_tm_skew(n));
177 tm_insert(treemap *t, void *key, void *val)
181 /* attempt the malloc before potentially splitting
182 * and skewing the tree, so the insertion can be a
183 * no-op on failure */
184 struct tm_node *prealloc = malloc(sizeof *prealloc);
185 struct map_pair *p = malloc(sizeof *p);
192 *p = (struct map_pair){.k = key, .v = val};
193 *prealloc = (struct tm_node){
194 .level = 1, .pair = p, .left = t->bottom, .right = t->bottom
197 t->root = internal_tm_insert(t, t->root, prealloc);
201 static struct tm_node *
202 internal_tm_remove(treemap *t, struct tm_node *n, void *key)
207 /* 1: search down the tree and set pointers last and deleted */
210 if (t->cmp(key, n->pair->k, t->cmp_aux) < 0)
211 n->left = internal_tm_remove(t, n->left, key);
215 n->right = internal_tm_remove(t, n->right, key);
218 /* 2: At the bottom of the tree, remove element if present */
220 if (n == t->last && t->deleted != t->bottom &&
221 t->cmp(key, t->deleted->pair->k, t->cmp_aux) == 0)
224 t->key_dtor(t->deleted->pair->k, t->dtor_aux);
226 t->val_dtor(t->deleted->pair->v, t->dtor_aux);
228 *t->deleted->pair = *n->pair;
229 t->deleted = t->bottom;
234 } /* 3: on the way back up, rebalance */
235 else if (n->left->level < n->level-1 ||
236 n->right->level < n->level-1) {
238 if (n->right->level > n->level)
239 n->right->level = n->level;
240 n = internal_tm_skew(n);
241 n->right = internal_tm_skew(n->right);
242 n->right->right = internal_tm_skew(n->right->right);
243 n = internal_tm_split(n);
244 n->right = internal_tm_split(n->right);
250 tm_remove(treemap *t, void *key)
254 t->root = internal_tm_remove(t, t->root, key);
255 return true; // TODO: return false if key wasn't found
259 internal_tm_clear(treemap *t, struct tm_node *n)
263 internal_tm_clear(t, n->left);
264 internal_tm_clear(t, n->right);
266 t->key_dtor(n->pair->k, t->dtor_aux);
268 t->val_dtor(n->pair->v, t->dtor_aux);
278 internal_tm_clear(t, t->root);
279 t->root = t->deleted = t->last = t->bottom;
283 tm_iter_begin(treemap *t)
287 struct tm_iter *i = malloc(sizeof *i);
295 *i = (struct tm_iter){
304 tm_iter_next(tm_iter *i)
308 if (l_is_empty(i->stack) && i->n == i->bottom)
309 return NULL; /* done */
310 if (i->n != i->bottom)
312 if (!l_append(i->stack, i->n))
313 return NULL; /* OOM */
315 return tm_iter_next(i);
317 struct tm_node *result = l_remove_last(i->stack);
318 i->n = result->right;
323 tm_iter_free(tm_iter *i)