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 _tm_length(const struct tm_node *n, const struct tm_node *bottom)
90 _tm_length(n->left, bottom) + _tm_length(n->right, bottom);
94 tm_length(const treemap *t)
96 return t ? _tm_length(t->root, t->bottom) : 0;
100 tm_is_empty(const treemap *t)
102 return tm_length(t) == 0;
106 _tm_at(const treemap *t, const struct tm_node *n, const void *key)
110 int x = t->cmp(key, n->pair->k, t->cmp_aux);
114 return _tm_at(t, n->left, key);
115 return _tm_at(t, n->right, key);
119 tm_at(const treemap *t, const void *key)
121 return t ? _tm_at(t, t->root, key) : NULL;
124 static struct tm_node *
125 _tm_skew(struct tm_node *n) {
126 if (n->level != n->left->level)
128 struct tm_node *left = n->left;
129 n->left = left->right;
135 static struct tm_node *
136 _tm_split(struct tm_node *n) {
137 if(n->right->right->level != n->level)
139 struct tm_node *right = n->right;
140 n->right = right->left;
147 static struct tm_node *
148 _tm_insert(treemap *t, struct tm_node *n, struct tm_node *prealloc)
152 int x = t->cmp(prealloc->pair->k, n->pair->k, t->cmp_aux);
154 n->left = _tm_insert(t, n->left, prealloc);
156 n->right = _tm_insert(t, n->right, prealloc);
159 /* prealloc was for naught, but we'll use its value */
160 if (n->pair->v != prealloc->pair->v && t->val_dtor)
161 t->val_dtor(n->pair->v, t->dtor_aux);
162 if (n->pair->k != prealloc->pair->k && t->key_dtor)
163 t->key_dtor(n->pair->k, t->dtor_aux);
164 *n->pair = *prealloc->pair;
165 free(prealloc->pair);
169 return _tm_split(_tm_skew(n));
173 tm_insert(treemap *t, void *key, void *val)
177 /* attempt the malloc before potentially splitting
178 * and skewing the tree, so the insertion can be a
179 * no-op on failure */
180 struct tm_node *prealloc = malloc(sizeof *prealloc);
181 struct map_pair *p = malloc(sizeof *p);
188 *p = (struct map_pair){.k = key, .v = val};
189 *prealloc = (struct tm_node){
190 .level = 1, .pair = p, .left = t->bottom, .right = t->bottom
193 t->root = _tm_insert(t, t->root, prealloc);
197 static struct tm_node *
198 _tm_remove(treemap *t, struct tm_node *n, void *key)
203 /* 1: search down the tree and set pointers last and deleted */
206 if (t->cmp(key, n->pair->k, t->cmp_aux) < 0)
207 n->left = _tm_remove(t, n->left, key);
211 n->right = _tm_remove(t, n->right, key);
214 /* 2: At the bottom of the tree, remove element if present */
216 if (n == t->last && t->deleted != t->bottom &&
217 t->cmp(key, t->deleted->pair->k, t->cmp_aux) == 0)
220 t->key_dtor(t->deleted->pair->k, t->dtor_aux);
222 t->val_dtor(t->deleted->pair->v, t->dtor_aux);
224 *t->deleted->pair = *n->pair;
225 t->deleted = t->bottom;
230 } /* 3: on the way back up, rebalance */
231 else if (n->left->level < n->level-1 ||
232 n->right->level < n->level-1) {
234 if (n->right->level > n->level)
235 n->right->level = n->level;
237 n->right = _tm_skew(n->right);
238 n->right->right = _tm_skew(n->right->right);
240 n->right = _tm_split(n->right);
246 tm_remove(treemap *t, void *key)
250 t->root = _tm_remove(t, t->root, key);
251 return true; // TODO: return false if key wasn't found
255 _tm_clear(treemap *t, struct tm_node *n)
259 _tm_clear(t, n->left);
260 _tm_clear(t, n->right);
262 t->key_dtor(n->pair->k, t->dtor_aux);
264 t->val_dtor(n->pair->v, t->dtor_aux);
274 _tm_clear(t, t->root);
275 t->root = t->deleted = t->last = t->bottom;
279 tm_iter_begin(treemap *t)
283 struct tm_iter *i = malloc(sizeof *i);
291 *i = (struct tm_iter){
300 tm_iter_next(tm_iter *i)
304 if (l_is_empty(i->stack) && i->n == i->bottom)
305 return NULL; /* done */
306 if (i->n != i->bottom)
308 if (!l_append(i->stack, i->n))
309 return NULL; /* OOM */
311 return tm_iter_next(i);
313 struct tm_node *result = l_remove_last(i->stack);
314 i->n = result->right;
319 tm_iter_free(tm_iter *i)