5 /* AA (Arne Andersson) Tree:
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
68 tm_dtor(treemap *t, dtor *key_dtor, dtor *val_dtor, void *dtor_aux)
72 t->key_dtor = key_dtor;
73 t->val_dtor = val_dtor;
74 t->dtor_aux = dtor_aux;
78 _tm_length(const struct tm_node *n, const struct tm_node *bottom)
83 _tm_length(n->left, bottom) + _tm_length(n->right, bottom);
87 tm_length(const treemap *t)
89 return t ? _tm_length(t->root, t->bottom) : 0;
93 tm_is_empty(const treemap *t)
95 return tm_length(t) == 0;
99 _tm_at(const treemap *t, const struct tm_node *n, const void *key)
103 int x = t->cmp(key, n->pair->k, t->cmp_aux);
107 return _tm_at(t, n->left, key);
108 return _tm_at(t, n->right, key);
112 tm_at(const treemap *t, const void *key)
114 return t ? _tm_at(t, t->root, key) : NULL;
117 static struct tm_node *
118 _tm_skew(struct tm_node *n) {
119 if (n->level != n->left->level)
121 struct tm_node *left = n->left;
122 n->left = left->right;
128 static struct tm_node *
129 _tm_split(struct tm_node *n) {
130 if(n->right->right->level != n->level)
132 struct tm_node *right = n->right;
133 n->right = right->left;
140 static struct tm_node *
141 _tm_insert(treemap *t, struct tm_node *n, struct tm_node *prealloc)
145 int x = t->cmp(prealloc->pair->k, n->pair->k, t->cmp_aux);
147 n->left = _tm_insert(t, n->left, prealloc);
149 n->right = _tm_insert(t, n->right, prealloc);
152 /* prealloc was for naught, but we'll use its value */
153 if (n->pair->v != prealloc->pair->v && t->val_dtor)
154 t->val_dtor(n->pair->v, t->dtor_aux);
155 if (n->pair->k != prealloc->pair->k && t->key_dtor)
156 t->key_dtor(n->pair->k, t->dtor_aux);
157 *n->pair = *prealloc->pair;
158 free(prealloc->pair);
162 return _tm_split(_tm_skew(n));
166 tm_insert(treemap *t, void *key, void *val)
170 /* attempt the malloc before potentially splitting
171 * and skewing the tree, so the insertion can be a
172 * no-op on failure */
173 struct tm_node *prealloc = malloc(sizeof *prealloc);
174 struct map_pair *p = malloc(sizeof *p);
181 *p = (struct map_pair){.k = key, .v = val};
182 *prealloc = (struct tm_node){
183 .level = 1, .pair = p, .left = t->bottom, .right = t->bottom
186 t->root = _tm_insert(t, t->root, prealloc);
190 static struct tm_node *
191 _tm_remove(treemap *t, struct tm_node *n, void *key)
196 /* 1: search down the tree and set pointers last and deleted */
199 if (t->cmp(key, n->pair->k, t->cmp_aux) < 0)
200 n->left = _tm_remove(t, n->left, key);
204 n->right = _tm_remove(t, n->right, key);
207 /* 2: At the bottom of the tree, remove element if present */
209 if (n == t->last && t->deleted != t->bottom &&
210 t->cmp(key, t->deleted->pair->k, t->cmp_aux) == 0)
213 t->key_dtor(t->deleted->pair->k, t->dtor_aux);
215 t->val_dtor(t->deleted->pair->v, t->dtor_aux);
217 *t->deleted->pair = *n->pair;
218 t->deleted = t->bottom;
223 } /* 3: on the way back up, rebalance */
224 else if (n->left->level < n->level-1 ||
225 n->right->level < n->level-1) {
227 if (n->right->level > n->level)
228 n->right->level = n->level;
230 n->right = _tm_skew(n->right);
231 n->right->right = _tm_skew(n->right->right);
233 n->right = _tm_split(n->right);
239 tm_remove(treemap *t, void *key)
243 t->root = _tm_remove(t, t->root, key);
244 return true; // TODO: return false if key wasn't found
248 _tm_clear(treemap *t, struct tm_node *n)
252 _tm_clear(t, n->left);
253 _tm_clear(t, n->right);
255 t->key_dtor(n->pair->k, t->dtor_aux);
257 t->val_dtor(n->pair->v, t->dtor_aux);
267 _tm_clear(t, t->root);
268 t->root = t->deleted = t->last = t->bottom;