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);
176 static struct tm_node *
177 _tm_remove(treemap *t, struct tm_node *n, void *key)
182 if (t->cmp(key, n->pair->k, t->cmp_aux) < 0)
183 n->left = _tm_remove(t, n->left, key);
187 n->right = _tm_remove(t, n->right, key);
190 if (n == t->last && t->deleted != t->bottom &&
191 t->cmp(key, t->deleted->pair->k, t->cmp_aux) == 0)
193 t->deleted->pair->k = n->pair->k;
194 t->deleted = t->bottom;
196 // TODO: free t->last and its data
197 } else if (n->left->level < n->level-1 ||
198 n->right->level < n->level-1) {
200 if (n->right->level > n->level)
201 n->right->level = n->level;
203 n->right = _tm_skew(n->right);
204 n->right->right = _tm_skew(n->right->right);
206 n->right = _tm_split(n->right);
212 tm_remove(treemap *t, void *key)
216 t->root = _tm_remove(t, t->root, key);
217 return true; // TODO: return false if key wasn't found