cannam@226
|
1 /*
|
cannam@226
|
2 Copyright 2011-2014 David Robillard <http://drobilla.net>
|
cannam@226
|
3
|
cannam@226
|
4 Permission to use, copy, modify, and/or distribute this software for any
|
cannam@226
|
5 purpose with or without fee is hereby granted, provided that the above
|
cannam@226
|
6 copyright notice and this permission notice appear in all copies.
|
cannam@226
|
7
|
cannam@226
|
8 THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
cannam@226
|
9 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
cannam@226
|
10 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
cannam@226
|
11 ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
cannam@226
|
12 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
cannam@226
|
13 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
cannam@226
|
14 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
cannam@226
|
15 */
|
cannam@226
|
16
|
cannam@226
|
17 #include <assert.h>
|
cannam@226
|
18 #include <stdint.h>
|
cannam@226
|
19 #include <stdio.h>
|
cannam@226
|
20 #include <stdlib.h>
|
cannam@226
|
21 #include <string.h>
|
cannam@226
|
22
|
cannam@245
|
23 #include "btree.h"
|
cannam@226
|
24
|
cannam@226
|
25 // #define ZIX_BTREE_DEBUG 1
|
cannam@226
|
26
|
cannam@226
|
27 #define ZIX_BTREE_PAGE_SIZE 4096
|
cannam@226
|
28 #define ZIX_BTREE_NODE_SPACE (ZIX_BTREE_PAGE_SIZE - 2 * sizeof(uint16_t))
|
cannam@226
|
29 #define ZIX_BTREE_LEAF_VALS ((ZIX_BTREE_NODE_SPACE / sizeof(void*)) - 1)
|
cannam@226
|
30 #define ZIX_BTREE_INODE_VALS (ZIX_BTREE_LEAF_VALS / 2)
|
cannam@226
|
31
|
cannam@226
|
32 struct ZixBTreeImpl {
|
cannam@226
|
33 ZixBTreeNode* root;
|
cannam@226
|
34 ZixDestroyFunc destroy;
|
cannam@226
|
35 ZixComparator cmp;
|
cannam@226
|
36 void* cmp_data;
|
cannam@226
|
37 size_t size;
|
cannam@226
|
38 unsigned height; ///< Number of levels, i.e. root only has height 1
|
cannam@226
|
39 };
|
cannam@226
|
40
|
cannam@226
|
41 struct ZixBTreeNodeImpl {
|
cannam@226
|
42 uint16_t is_leaf;
|
cannam@226
|
43 uint16_t n_vals;
|
cannam@226
|
44 // On 64-bit we rely on some padding here to get page-sized nodes
|
cannam@226
|
45 void* vals[ZIX_BTREE_INODE_VALS]; // ZIX_BTREE_LEAF_VALS for leaves
|
cannam@226
|
46 ZixBTreeNode* children[ZIX_BTREE_INODE_VALS + 1]; // Nonexistent for leaves
|
cannam@226
|
47 };
|
cannam@226
|
48
|
cannam@226
|
49 typedef struct {
|
cannam@226
|
50 ZixBTreeNode* node;
|
cannam@226
|
51 unsigned index;
|
cannam@226
|
52 } ZixBTreeIterFrame;
|
cannam@226
|
53
|
cannam@226
|
54 struct ZixBTreeIterImpl {
|
cannam@226
|
55 unsigned level; ///< Current level in stack
|
cannam@226
|
56 ZixBTreeIterFrame stack[]; ///< Position stack
|
cannam@226
|
57 };
|
cannam@226
|
58
|
cannam@226
|
59 #ifdef ZIX_BTREE_DEBUG
|
cannam@226
|
60
|
cannam@226
|
61 ZIX_PRIVATE void
|
cannam@226
|
62 print_node(const ZixBTreeNode* n, const char* prefix)
|
cannam@226
|
63 {
|
cannam@226
|
64 printf("%s[", prefix);
|
cannam@226
|
65 for (uint16_t v = 0; v < n->n_vals; ++v) {
|
cannam@226
|
66 printf(" %lu", (uintptr_t)n->vals[v]);
|
cannam@226
|
67 }
|
cannam@226
|
68 printf(" ]\n");
|
cannam@226
|
69 }
|
cannam@226
|
70
|
cannam@226
|
71 ZIX_PRIVATE void
|
cannam@226
|
72 print_tree(const ZixBTreeNode* parent, const ZixBTreeNode* node, int level)
|
cannam@226
|
73 {
|
cannam@226
|
74 if (node) {
|
cannam@226
|
75 if (!parent) {
|
cannam@226
|
76 printf("TREE {\n");
|
cannam@226
|
77 }
|
cannam@226
|
78 for (int i = 0; i < level + 1; ++i) {
|
cannam@226
|
79 printf(" ");
|
cannam@226
|
80 }
|
cannam@226
|
81 print_node(node, "");
|
cannam@226
|
82 if (!node->is_leaf) {
|
cannam@226
|
83 for (uint16_t i = 0; i < node->n_vals + 1; ++i) {
|
cannam@226
|
84 print_tree(node, node->children[i], level + 1);
|
cannam@226
|
85 }
|
cannam@226
|
86 }
|
cannam@226
|
87 if (!parent) {
|
cannam@226
|
88 printf("}\n");
|
cannam@226
|
89 }
|
cannam@226
|
90 }
|
cannam@226
|
91 }
|
cannam@226
|
92
|
cannam@226
|
93 #endif // ZIX_BTREE_DEBUG
|
cannam@226
|
94
|
cannam@226
|
95 ZIX_PRIVATE ZixBTreeNode*
|
cannam@226
|
96 zix_btree_node_new(const bool leaf)
|
cannam@226
|
97 {
|
cannam@226
|
98 assert(sizeof(ZixBTreeNode) == ZIX_BTREE_PAGE_SIZE);
|
cannam@226
|
99 ZixBTreeNode* node = (ZixBTreeNode*)malloc(sizeof(ZixBTreeNode));
|
cannam@226
|
100 if (node) {
|
cannam@226
|
101 node->is_leaf = leaf;
|
cannam@226
|
102 node->n_vals = 0;
|
cannam@226
|
103 }
|
cannam@226
|
104 return node;
|
cannam@226
|
105 }
|
cannam@226
|
106
|
cannam@226
|
107 ZIX_API ZixBTree*
|
cannam@226
|
108 zix_btree_new(const ZixComparator cmp,
|
cannam@226
|
109 void* const cmp_data,
|
cannam@226
|
110 const ZixDestroyFunc destroy)
|
cannam@226
|
111 {
|
cannam@226
|
112 ZixBTree* t = (ZixBTree*)malloc(sizeof(ZixBTree));
|
cannam@226
|
113 if (t) {
|
cannam@226
|
114 t->root = zix_btree_node_new(true);
|
cannam@226
|
115 t->destroy = destroy;
|
cannam@226
|
116 t->cmp = cmp;
|
cannam@226
|
117 t->cmp_data = cmp_data;
|
cannam@226
|
118 t->size = 0;
|
cannam@226
|
119 t->height = 1;
|
cannam@226
|
120 if (!t->root) {
|
cannam@226
|
121 free(t);
|
cannam@226
|
122 return NULL;
|
cannam@226
|
123 }
|
cannam@226
|
124 }
|
cannam@226
|
125 return t;
|
cannam@226
|
126 }
|
cannam@226
|
127
|
cannam@226
|
128 ZIX_PRIVATE void
|
cannam@226
|
129 zix_btree_free_rec(ZixBTree* const t, ZixBTreeNode* const n)
|
cannam@226
|
130 {
|
cannam@226
|
131 if (n) {
|
cannam@226
|
132 if (t->destroy) {
|
cannam@226
|
133 for (uint16_t i = 0; i < n->n_vals; ++i) {
|
cannam@226
|
134 t->destroy(n->vals[i]);
|
cannam@226
|
135 }
|
cannam@226
|
136 }
|
cannam@226
|
137 if (!n->is_leaf) {
|
cannam@226
|
138 for (uint16_t i = 0; i < n->n_vals + 1; ++i) {
|
cannam@226
|
139 zix_btree_free_rec(t, n->children[i]);
|
cannam@226
|
140 }
|
cannam@226
|
141 }
|
cannam@226
|
142 free(n);
|
cannam@226
|
143 }
|
cannam@226
|
144 }
|
cannam@226
|
145
|
cannam@226
|
146 ZIX_API void
|
cannam@226
|
147 zix_btree_free(ZixBTree* const t)
|
cannam@226
|
148 {
|
cannam@226
|
149 if (t) {
|
cannam@226
|
150 zix_btree_free_rec(t, t->root);
|
cannam@226
|
151 free(t);
|
cannam@226
|
152 }
|
cannam@226
|
153 }
|
cannam@226
|
154
|
cannam@226
|
155 ZIX_API size_t
|
cannam@226
|
156 zix_btree_size(const ZixBTree* const t)
|
cannam@226
|
157 {
|
cannam@226
|
158 return t->size;
|
cannam@226
|
159 }
|
cannam@226
|
160
|
cannam@226
|
161 ZIX_PRIVATE uint16_t
|
cannam@226
|
162 zix_btree_max_vals(const ZixBTreeNode* const node)
|
cannam@226
|
163 {
|
cannam@226
|
164 return node->is_leaf ? ZIX_BTREE_LEAF_VALS : ZIX_BTREE_INODE_VALS;
|
cannam@226
|
165 }
|
cannam@226
|
166
|
cannam@226
|
167 ZIX_PRIVATE uint16_t
|
cannam@226
|
168 zix_btree_min_vals(const ZixBTreeNode* const node)
|
cannam@226
|
169 {
|
cannam@226
|
170 return ((zix_btree_max_vals(node) + 1) / 2) - 1;
|
cannam@226
|
171 }
|
cannam@226
|
172
|
cannam@226
|
173 /** Shift pointers in `array` of length `n` right starting at `i`. */
|
cannam@226
|
174 ZIX_PRIVATE void
|
cannam@226
|
175 zix_btree_ainsert(void** const array,
|
cannam@226
|
176 const uint16_t n,
|
cannam@226
|
177 const uint16_t i,
|
cannam@226
|
178 void* const e)
|
cannam@226
|
179 {
|
cannam@226
|
180 memmove(array + i + 1, array + i, (n - i) * sizeof(e));
|
cannam@226
|
181 array[i] = e;
|
cannam@226
|
182 }
|
cannam@226
|
183
|
cannam@226
|
184 /** Erase element `i` in `array` of length `n` and return erased element. */
|
cannam@226
|
185 ZIX_PRIVATE void*
|
cannam@226
|
186 zix_btree_aerase(void** const array, const uint16_t n, const uint16_t i)
|
cannam@226
|
187 {
|
cannam@226
|
188 void* const ret = array[i];
|
cannam@226
|
189 memmove(array + i, array + i + 1, (n - i) * sizeof(ret));
|
cannam@226
|
190 return ret;
|
cannam@226
|
191 }
|
cannam@226
|
192
|
cannam@226
|
193 /** Split lhs, the i'th child of `n`, into two nodes. */
|
cannam@226
|
194 ZIX_PRIVATE ZixBTreeNode*
|
cannam@226
|
195 zix_btree_split_child(ZixBTreeNode* const n,
|
cannam@226
|
196 const uint16_t i,
|
cannam@226
|
197 ZixBTreeNode* const lhs)
|
cannam@226
|
198 {
|
cannam@226
|
199 assert(lhs->n_vals == zix_btree_max_vals(lhs));
|
cannam@226
|
200 assert(n->n_vals < ZIX_BTREE_INODE_VALS);
|
cannam@226
|
201 assert(i < n->n_vals + 1);
|
cannam@226
|
202 assert(n->children[i] == lhs);
|
cannam@226
|
203
|
cannam@226
|
204 const uint16_t max_n_vals = zix_btree_max_vals(lhs);
|
cannam@226
|
205 ZixBTreeNode* rhs = zix_btree_node_new(lhs->is_leaf);
|
cannam@226
|
206 if (!rhs) {
|
cannam@226
|
207 return NULL;
|
cannam@226
|
208 }
|
cannam@226
|
209
|
cannam@226
|
210 // LHS and RHS get roughly half, less the middle value which moves up
|
cannam@226
|
211 lhs->n_vals = max_n_vals / 2;
|
cannam@226
|
212 rhs->n_vals = max_n_vals - lhs->n_vals - 1;
|
cannam@226
|
213
|
cannam@226
|
214 // Copy large half of values from LHS to new RHS node
|
cannam@226
|
215 memcpy(rhs->vals,
|
cannam@226
|
216 lhs->vals + lhs->n_vals + 1,
|
cannam@226
|
217 rhs->n_vals * sizeof(void*));
|
cannam@226
|
218
|
cannam@226
|
219 // Copy large half of children from LHS to new RHS node
|
cannam@226
|
220 if (!lhs->is_leaf) {
|
cannam@226
|
221 memcpy(rhs->children,
|
cannam@226
|
222 lhs->children + lhs->n_vals + 1,
|
cannam@226
|
223 (rhs->n_vals + 1) * sizeof(ZixBTreeNode*));
|
cannam@226
|
224 }
|
cannam@226
|
225
|
cannam@226
|
226 // Move middle value up to parent
|
cannam@226
|
227 zix_btree_ainsert(n->vals, n->n_vals, i, lhs->vals[lhs->n_vals]);
|
cannam@226
|
228
|
cannam@226
|
229 // Insert new RHS node in parent at position i
|
cannam@226
|
230 zix_btree_ainsert((void**)n->children, ++n->n_vals, i + 1, rhs);
|
cannam@226
|
231
|
cannam@226
|
232 return rhs;
|
cannam@226
|
233 }
|
cannam@226
|
234
|
cannam@226
|
235 /** Find the first value in `n` that is not less than `e` (lower bound). */
|
cannam@226
|
236 ZIX_PRIVATE uint16_t
|
cannam@226
|
237 zix_btree_node_find(const ZixBTree* const t,
|
cannam@226
|
238 const ZixBTreeNode* const n,
|
cannam@226
|
239 const void* const e,
|
cannam@226
|
240 bool* const equal)
|
cannam@226
|
241 {
|
cannam@226
|
242 uint16_t first = 0;
|
cannam@226
|
243 uint16_t len = n->n_vals;
|
cannam@226
|
244 while (len > 0) {
|
cannam@226
|
245 const uint16_t half = len >> 1;
|
cannam@226
|
246 const uint16_t i = first + half;
|
cannam@226
|
247 const int cmp = t->cmp(n->vals[i], e, t->cmp_data);
|
cannam@226
|
248 if (cmp == 0) {
|
cannam@226
|
249 *equal = true;
|
cannam@226
|
250 len = half; // Keep searching for wildcard matches
|
cannam@226
|
251 } else if (cmp < 0) {
|
cannam@226
|
252 const uint16_t chop = half + 1;
|
cannam@226
|
253 first += chop;
|
cannam@226
|
254 len -= chop;
|
cannam@226
|
255 } else {
|
cannam@226
|
256 len = half;
|
cannam@226
|
257 }
|
cannam@226
|
258 }
|
cannam@226
|
259 assert(!*equal || t->cmp(n->vals[first], e, t->cmp_data) == 0);
|
cannam@226
|
260 return first;
|
cannam@226
|
261 }
|
cannam@226
|
262
|
cannam@226
|
263 ZIX_API ZixStatus
|
cannam@226
|
264 zix_btree_insert(ZixBTree* const t, void* const e)
|
cannam@226
|
265 {
|
cannam@226
|
266 ZixBTreeNode* parent = NULL; // Parent of n
|
cannam@226
|
267 ZixBTreeNode* n = t->root; // Current node
|
cannam@226
|
268 uint16_t i = 0; // Index of n in parent
|
cannam@226
|
269 while (n) {
|
cannam@226
|
270 if (n->n_vals == zix_btree_max_vals(n)) {
|
cannam@226
|
271 // Node is full, split to ensure there is space for a leaf split
|
cannam@226
|
272 if (!parent) {
|
cannam@226
|
273 // Root is full, grow tree upwards
|
cannam@226
|
274 if (!(parent = zix_btree_node_new(false))) {
|
cannam@226
|
275 return ZIX_STATUS_NO_MEM;
|
cannam@226
|
276 }
|
cannam@226
|
277 t->root = parent;
|
cannam@226
|
278 parent->children[0] = n;
|
cannam@226
|
279 ++t->height;
|
cannam@226
|
280 }
|
cannam@226
|
281
|
cannam@226
|
282 ZixBTreeNode* const rhs = zix_btree_split_child(parent, i, n);
|
cannam@226
|
283 if (!rhs) {
|
cannam@226
|
284 return ZIX_STATUS_NO_MEM;
|
cannam@226
|
285 }
|
cannam@226
|
286
|
cannam@226
|
287 const int cmp = t->cmp(parent->vals[i], e, t->cmp_data);
|
cannam@226
|
288 if (cmp == 0) {
|
cannam@226
|
289 return ZIX_STATUS_EXISTS;
|
cannam@226
|
290 } else if (cmp < 0) {
|
cannam@226
|
291 // Move to new RHS
|
cannam@226
|
292 n = rhs;
|
cannam@226
|
293 ++i;
|
cannam@226
|
294 }
|
cannam@226
|
295 }
|
cannam@226
|
296
|
cannam@226
|
297 assert(!parent || parent->children[i] == n);
|
cannam@226
|
298
|
cannam@226
|
299 bool equal = false;
|
cannam@226
|
300 i = zix_btree_node_find(t, n, e, &equal);
|
cannam@226
|
301 if (equal) {
|
cannam@226
|
302 return ZIX_STATUS_EXISTS;
|
cannam@226
|
303 } else if (!n->is_leaf) {
|
cannam@226
|
304 // Descend to child node left of value
|
cannam@226
|
305 parent = n;
|
cannam@226
|
306 n = n->children[i];
|
cannam@226
|
307 } else {
|
cannam@226
|
308 // Insert into internal node
|
cannam@226
|
309 zix_btree_ainsert(n->vals, n->n_vals++, i, e);
|
cannam@226
|
310 break;
|
cannam@226
|
311 }
|
cannam@226
|
312 }
|
cannam@226
|
313
|
cannam@226
|
314 ++t->size;
|
cannam@226
|
315
|
cannam@226
|
316 return ZIX_STATUS_SUCCESS;
|
cannam@226
|
317 }
|
cannam@226
|
318
|
cannam@226
|
319 ZIX_PRIVATE ZixBTreeIter*
|
cannam@226
|
320 zix_btree_iter_new(const ZixBTree* const t)
|
cannam@226
|
321 {
|
cannam@226
|
322 const size_t s = t->height * sizeof(ZixBTreeIterFrame);
|
cannam@226
|
323 ZixBTreeIter* const i = (ZixBTreeIter*)malloc(sizeof(ZixBTreeIter) + s);
|
cannam@226
|
324 if (i) {
|
cannam@226
|
325 i->level = 0;
|
cannam@226
|
326 }
|
cannam@226
|
327 return i;
|
cannam@226
|
328 }
|
cannam@226
|
329
|
cannam@226
|
330 ZIX_PRIVATE void
|
cannam@226
|
331 zix_btree_iter_set_frame(ZixBTreeIter* const ti,
|
cannam@226
|
332 ZixBTreeNode* const n,
|
cannam@226
|
333 const uint16_t i)
|
cannam@226
|
334 {
|
cannam@226
|
335 if (ti) {
|
cannam@226
|
336 ti->stack[ti->level].node = n;
|
cannam@226
|
337 ti->stack[ti->level].index = i;
|
cannam@226
|
338 }
|
cannam@226
|
339 }
|
cannam@226
|
340
|
cannam@226
|
341 ZIX_PRIVATE bool
|
cannam@226
|
342 zix_btree_node_is_minimal(ZixBTreeNode* const n)
|
cannam@226
|
343 {
|
cannam@226
|
344 assert(n->n_vals >= zix_btree_min_vals(n));
|
cannam@226
|
345 return n->n_vals == zix_btree_min_vals(n);
|
cannam@226
|
346 }
|
cannam@226
|
347
|
cannam@226
|
348 /** Enlarge left child by stealing a value from its right sibling. */
|
cannam@226
|
349 ZIX_PRIVATE ZixBTreeNode*
|
cannam@226
|
350 zix_btree_rotate_left(ZixBTreeNode* const parent, const uint16_t i)
|
cannam@226
|
351 {
|
cannam@226
|
352 ZixBTreeNode* const lhs = parent->children[i];
|
cannam@226
|
353 ZixBTreeNode* const rhs = parent->children[i + 1];
|
cannam@226
|
354
|
cannam@226
|
355 // Move parent value to end of LHS
|
cannam@226
|
356 lhs->vals[lhs->n_vals++] = parent->vals[i];
|
cannam@226
|
357
|
cannam@226
|
358 // Move first child pointer from RHS to end of LHS
|
cannam@226
|
359 if (!lhs->is_leaf) {
|
cannam@226
|
360 lhs->children[lhs->n_vals] = (ZixBTreeNode*)zix_btree_aerase(
|
cannam@226
|
361 (void**)rhs->children, rhs->n_vals, 0);
|
cannam@226
|
362 }
|
cannam@226
|
363
|
cannam@226
|
364 // Move first value in RHS to parent
|
cannam@226
|
365 parent->vals[i] = zix_btree_aerase(rhs->vals, --rhs->n_vals, 0);
|
cannam@226
|
366
|
cannam@226
|
367 return lhs;
|
cannam@226
|
368 }
|
cannam@226
|
369
|
cannam@226
|
370 /** Enlarge right child by stealing a value from its left sibling. */
|
cannam@226
|
371 ZIX_PRIVATE ZixBTreeNode*
|
cannam@226
|
372 zix_btree_rotate_right(ZixBTreeNode* const parent, const uint16_t i)
|
cannam@226
|
373 {
|
cannam@226
|
374 ZixBTreeNode* const lhs = parent->children[i - 1];
|
cannam@226
|
375 ZixBTreeNode* const rhs = parent->children[i];
|
cannam@226
|
376
|
cannam@226
|
377 // Prepend parent value to RHS
|
cannam@226
|
378 zix_btree_ainsert(rhs->vals, rhs->n_vals++, 0, parent->vals[i - 1]);
|
cannam@226
|
379
|
cannam@226
|
380 // Move last child pointer from LHS and prepend to RHS
|
cannam@226
|
381 if (!lhs->is_leaf) {
|
cannam@226
|
382 zix_btree_ainsert((void**)rhs->children,
|
cannam@226
|
383 rhs->n_vals,
|
cannam@226
|
384 0,
|
cannam@226
|
385 lhs->children[lhs->n_vals]);
|
cannam@226
|
386 }
|
cannam@226
|
387
|
cannam@226
|
388 // Move last value from LHS to parent
|
cannam@226
|
389 parent->vals[i - 1] = lhs->vals[--lhs->n_vals];
|
cannam@226
|
390
|
cannam@226
|
391 return rhs;
|
cannam@226
|
392 }
|
cannam@226
|
393
|
cannam@226
|
394 /** Move n[i] down, merge the left and right child, return the merged node. */
|
cannam@226
|
395 ZIX_PRIVATE ZixBTreeNode*
|
cannam@226
|
396 zix_btree_merge(ZixBTree* const t, ZixBTreeNode* const n, const uint16_t i)
|
cannam@226
|
397 {
|
cannam@226
|
398 ZixBTreeNode* const lhs = n->children[i];
|
cannam@226
|
399 ZixBTreeNode* const rhs = n->children[i + 1];
|
cannam@226
|
400
|
cannam@226
|
401 assert(zix_btree_node_is_minimal(n->children[i]));
|
cannam@226
|
402 assert(lhs->n_vals + rhs->n_vals < zix_btree_max_vals(lhs));
|
cannam@226
|
403
|
cannam@226
|
404 // Move parent value to end of LHS
|
cannam@226
|
405 lhs->vals[lhs->n_vals++] = zix_btree_aerase(n->vals, n->n_vals, i);
|
cannam@226
|
406
|
cannam@226
|
407 // Erase corresponding child pointer (to RHS) in parent
|
cannam@226
|
408 zix_btree_aerase((void**)n->children, n->n_vals, i + 1);
|
cannam@226
|
409
|
cannam@226
|
410 // Add everything from RHS to end of LHS
|
cannam@226
|
411 memcpy(lhs->vals + lhs->n_vals, rhs->vals, rhs->n_vals * sizeof(void*));
|
cannam@226
|
412 if (!lhs->is_leaf) {
|
cannam@226
|
413 memcpy(lhs->children + lhs->n_vals,
|
cannam@226
|
414 rhs->children,
|
cannam@226
|
415 (rhs->n_vals + 1) * sizeof(void*));
|
cannam@226
|
416 }
|
cannam@226
|
417 lhs->n_vals += rhs->n_vals;
|
cannam@226
|
418
|
cannam@226
|
419 if (--n->n_vals == 0) {
|
cannam@226
|
420 // Root is now empty, replace it with its only child
|
cannam@226
|
421 assert(n == t->root);
|
cannam@226
|
422 t->root = lhs;
|
cannam@226
|
423 free(n);
|
cannam@226
|
424 }
|
cannam@226
|
425
|
cannam@226
|
426 free(rhs);
|
cannam@226
|
427 return lhs;
|
cannam@226
|
428 }
|
cannam@226
|
429
|
cannam@226
|
430 /** Remove and return the min value from the subtree rooted at `n`. */
|
cannam@226
|
431 ZIX_PRIVATE void*
|
cannam@226
|
432 zix_btree_remove_min(ZixBTree* const t, ZixBTreeNode* n)
|
cannam@226
|
433 {
|
cannam@226
|
434 while (!n->is_leaf) {
|
cannam@226
|
435 if (zix_btree_node_is_minimal(n->children[0])) {
|
cannam@226
|
436 // Leftmost child is minimal, must expand
|
cannam@226
|
437 if (!zix_btree_node_is_minimal(n->children[1])) {
|
cannam@226
|
438 // Child's right sibling has at least one key to steal
|
cannam@226
|
439 n = zix_btree_rotate_left(n, 0);
|
cannam@226
|
440 } else {
|
cannam@226
|
441 // Both child and right sibling are minimal, merge
|
cannam@226
|
442 n = zix_btree_merge(t, n, 0);
|
cannam@226
|
443 }
|
cannam@226
|
444 } else {
|
cannam@226
|
445 n = n->children[0];
|
cannam@226
|
446 }
|
cannam@226
|
447 }
|
cannam@226
|
448
|
cannam@226
|
449 return zix_btree_aerase(n->vals, --n->n_vals, 0);
|
cannam@226
|
450 }
|
cannam@226
|
451
|
cannam@226
|
452 /** Remove and return the max value from the subtree rooted at `n`. */
|
cannam@226
|
453 ZIX_PRIVATE void*
|
cannam@226
|
454 zix_btree_remove_max(ZixBTree* const t, ZixBTreeNode* n)
|
cannam@226
|
455 {
|
cannam@226
|
456 while (!n->is_leaf) {
|
cannam@226
|
457 if (zix_btree_node_is_minimal(n->children[n->n_vals])) {
|
cannam@226
|
458 // Leftmost child is minimal, must expand
|
cannam@226
|
459 if (!zix_btree_node_is_minimal(n->children[n->n_vals - 1])) {
|
cannam@226
|
460 // Child's left sibling has at least one key to steal
|
cannam@226
|
461 n = zix_btree_rotate_right(n, n->n_vals);
|
cannam@226
|
462 } else {
|
cannam@226
|
463 // Both child and left sibling are minimal, merge
|
cannam@226
|
464 n = zix_btree_merge(t, n, n->n_vals - 1);
|
cannam@226
|
465 }
|
cannam@226
|
466 } else {
|
cannam@226
|
467 n = n->children[n->n_vals];
|
cannam@226
|
468 }
|
cannam@226
|
469 }
|
cannam@226
|
470
|
cannam@226
|
471 return n->vals[--n->n_vals];
|
cannam@226
|
472 }
|
cannam@226
|
473
|
cannam@226
|
474 ZIX_API ZixStatus
|
cannam@226
|
475 zix_btree_remove(ZixBTree* const t,
|
cannam@226
|
476 const void* const e,
|
cannam@226
|
477 void** const out,
|
cannam@226
|
478 ZixBTreeIter** const next)
|
cannam@226
|
479 {
|
cannam@226
|
480 ZixBTreeNode* n = t->root;
|
cannam@226
|
481 ZixBTreeIter* ti = NULL;
|
cannam@226
|
482 const bool user_iter = next && *next;
|
cannam@226
|
483 if (next) {
|
cannam@226
|
484 if (!*next && !(*next = zix_btree_iter_new(t))) {
|
cannam@226
|
485 return ZIX_STATUS_NO_MEM;
|
cannam@226
|
486 }
|
cannam@226
|
487 ti = *next;
|
cannam@226
|
488 ti->level = 0;
|
cannam@226
|
489 }
|
cannam@226
|
490
|
cannam@226
|
491 while (true) {
|
cannam@226
|
492 /* To remove in a single walk down, the tree is adjusted along the way
|
cannam@226
|
493 so that the current node always has at least one more value than the
|
cannam@226
|
494 minimum required in general. Thus, there is always room to remove
|
cannam@226
|
495 without adjusting on the way back up. */
|
cannam@226
|
496 assert(n == t->root || !zix_btree_node_is_minimal(n));
|
cannam@226
|
497
|
cannam@226
|
498 bool equal = false;
|
cannam@226
|
499 const uint16_t i = zix_btree_node_find(t, n, e, &equal);
|
cannam@226
|
500 zix_btree_iter_set_frame(ti, n, i);
|
cannam@226
|
501 if (n->is_leaf) {
|
cannam@226
|
502 if (equal) {
|
cannam@226
|
503 // Found in leaf node
|
cannam@226
|
504 *out = zix_btree_aerase(n->vals, --n->n_vals, i);
|
cannam@226
|
505 if (ti && i == n->n_vals) {
|
cannam@226
|
506 if (i == 0) {
|
cannam@226
|
507 ti->stack[ti->level = 0].node = NULL;
|
cannam@226
|
508 } else {
|
cannam@226
|
509 --ti->stack[ti->level].index;
|
cannam@226
|
510 zix_btree_iter_increment(ti);
|
cannam@226
|
511 }
|
cannam@226
|
512 }
|
cannam@226
|
513 --t->size;
|
cannam@226
|
514 return ZIX_STATUS_SUCCESS;
|
cannam@226
|
515 } else {
|
cannam@226
|
516 // Not found in leaf node, or tree
|
cannam@226
|
517 if (ti && !user_iter) {
|
cannam@226
|
518 zix_btree_iter_free(ti);
|
cannam@226
|
519 *next = NULL;
|
cannam@226
|
520 }
|
cannam@226
|
521 return ZIX_STATUS_NOT_FOUND;
|
cannam@226
|
522 }
|
cannam@226
|
523 } else if (equal) {
|
cannam@226
|
524 // Found in internal node
|
cannam@226
|
525 if (!zix_btree_node_is_minimal(n->children[i])) {
|
cannam@226
|
526 // Left child can remove without merge
|
cannam@226
|
527 *out = n->vals[i];
|
cannam@226
|
528 n->vals[i] = zix_btree_remove_max(t, n->children[i]);
|
cannam@226
|
529 --t->size;
|
cannam@226
|
530 return ZIX_STATUS_SUCCESS;
|
cannam@226
|
531 } else if (!zix_btree_node_is_minimal(n->children[i + 1])) {
|
cannam@226
|
532 // Right child can remove without merge
|
cannam@226
|
533 *out = n->vals[i];
|
cannam@226
|
534 n->vals[i] = zix_btree_remove_min(t, n->children[i + 1]);
|
cannam@226
|
535 --t->size;
|
cannam@226
|
536 return ZIX_STATUS_SUCCESS;
|
cannam@226
|
537 } else {
|
cannam@226
|
538 // Both preceding and succeeding child are minimal
|
cannam@226
|
539 n = zix_btree_merge(t, n, i);
|
cannam@226
|
540 }
|
cannam@226
|
541 } else {
|
cannam@226
|
542 // Not found in internal node, key is in/under children[i]
|
cannam@226
|
543 if (zix_btree_node_is_minimal(n->children[i])) {
|
cannam@226
|
544 if (i > 0 && !zix_btree_node_is_minimal(n->children[i - 1])) {
|
cannam@226
|
545 // Steal a key from child's left sibling
|
cannam@226
|
546 n = zix_btree_rotate_right(n, i);
|
cannam@226
|
547 } else if (i < n->n_vals &&
|
cannam@226
|
548 !zix_btree_node_is_minimal(n->children[i + 1])) {
|
cannam@226
|
549 // Steal a key from child's right sibling
|
cannam@226
|
550 n = zix_btree_rotate_left(n, i);
|
cannam@226
|
551 } else {
|
cannam@226
|
552 // Both child's siblings are minimal, merge them
|
cannam@226
|
553 if (i < n->n_vals) {
|
cannam@226
|
554 n = zix_btree_merge(t, n, i);
|
cannam@226
|
555 } else {
|
cannam@226
|
556 n = zix_btree_merge(t, n, i - 1);
|
cannam@226
|
557 if (ti) {
|
cannam@226
|
558 --ti->stack[ti->level].index;
|
cannam@226
|
559 }
|
cannam@226
|
560 }
|
cannam@226
|
561 }
|
cannam@226
|
562 } else {
|
cannam@226
|
563 n = n->children[i];
|
cannam@226
|
564 }
|
cannam@226
|
565 }
|
cannam@226
|
566 if (ti) {
|
cannam@226
|
567 ++ti->level;
|
cannam@226
|
568 }
|
cannam@226
|
569 }
|
cannam@226
|
570
|
cannam@226
|
571 assert(false); // Not reached
|
cannam@226
|
572 return ZIX_STATUS_ERROR;
|
cannam@226
|
573 }
|
cannam@226
|
574
|
cannam@226
|
575 ZIX_API ZixStatus
|
cannam@226
|
576 zix_btree_find(const ZixBTree* const t,
|
cannam@226
|
577 const void* const e,
|
cannam@226
|
578 ZixBTreeIter** const ti)
|
cannam@226
|
579 {
|
cannam@226
|
580 ZixBTreeNode* n = t->root;
|
cannam@226
|
581 if (!(*ti = zix_btree_iter_new(t))) {
|
cannam@226
|
582 return ZIX_STATUS_NO_MEM;
|
cannam@226
|
583 }
|
cannam@226
|
584
|
cannam@226
|
585 while (n) {
|
cannam@226
|
586 bool equal = false;
|
cannam@226
|
587 const uint16_t i = zix_btree_node_find(t, n, e, &equal);
|
cannam@226
|
588
|
cannam@226
|
589 zix_btree_iter_set_frame(*ti, n, i);
|
cannam@226
|
590
|
cannam@226
|
591 if (equal) {
|
cannam@226
|
592 return ZIX_STATUS_SUCCESS;
|
cannam@226
|
593 } else if (n->is_leaf) {
|
cannam@226
|
594 break;
|
cannam@226
|
595 } else {
|
cannam@226
|
596 ++(*ti)->level;
|
cannam@226
|
597 n = n->children[i];
|
cannam@226
|
598 }
|
cannam@226
|
599 }
|
cannam@226
|
600
|
cannam@226
|
601 zix_btree_iter_free(*ti);
|
cannam@226
|
602 *ti = NULL;
|
cannam@226
|
603 return ZIX_STATUS_NOT_FOUND;
|
cannam@226
|
604 }
|
cannam@226
|
605
|
cannam@226
|
606 ZIX_API ZixStatus
|
cannam@226
|
607 zix_btree_lower_bound(const ZixBTree* const t,
|
cannam@226
|
608 const void* const e,
|
cannam@226
|
609 ZixBTreeIter** const ti)
|
cannam@226
|
610 {
|
cannam@226
|
611 if (!t) {
|
cannam@226
|
612 *ti = NULL;
|
cannam@226
|
613 return ZIX_STATUS_BAD_ARG;
|
cannam@226
|
614 }
|
cannam@226
|
615
|
cannam@226
|
616 ZixBTreeNode* n = t->root;
|
cannam@226
|
617 bool found = false;
|
cannam@226
|
618 unsigned found_level = 0;
|
cannam@226
|
619 if (!(*ti = zix_btree_iter_new(t))) {
|
cannam@226
|
620 return ZIX_STATUS_NO_MEM;
|
cannam@226
|
621 }
|
cannam@226
|
622
|
cannam@226
|
623 while (n) {
|
cannam@226
|
624 bool equal = false;
|
cannam@226
|
625 const uint16_t i = zix_btree_node_find(t, n, e, &equal);
|
cannam@226
|
626
|
cannam@226
|
627 zix_btree_iter_set_frame(*ti, n, i);
|
cannam@226
|
628
|
cannam@226
|
629 if (equal) {
|
cannam@226
|
630 found_level = (*ti)->level;
|
cannam@226
|
631 found = true;
|
cannam@226
|
632 }
|
cannam@226
|
633
|
cannam@226
|
634 if (n->is_leaf) {
|
cannam@226
|
635 break;
|
cannam@226
|
636 } else {
|
cannam@226
|
637 ++(*ti)->level;
|
cannam@226
|
638 n = n->children[i];
|
cannam@226
|
639 assert(n);
|
cannam@226
|
640 }
|
cannam@226
|
641 }
|
cannam@226
|
642
|
cannam@226
|
643 const ZixBTreeIterFrame* const frame = &(*ti)->stack[(*ti)->level];
|
cannam@226
|
644 if (frame->index == frame->node->n_vals) {
|
cannam@226
|
645 if (found) {
|
cannam@226
|
646 // Found on a previous level but went too far
|
cannam@226
|
647 (*ti)->level = found_level;
|
cannam@226
|
648 } else {
|
cannam@226
|
649 // Reached end (key is greater than everything in tree)
|
cannam@226
|
650 (*ti)->stack[0].node = NULL;
|
cannam@226
|
651 }
|
cannam@226
|
652 }
|
cannam@226
|
653
|
cannam@226
|
654 return ZIX_STATUS_SUCCESS;
|
cannam@226
|
655 }
|
cannam@226
|
656
|
cannam@226
|
657 ZIX_API void*
|
cannam@226
|
658 zix_btree_get(const ZixBTreeIter* const ti)
|
cannam@226
|
659 {
|
cannam@226
|
660 const ZixBTreeIterFrame* const frame = &ti->stack[ti->level];
|
cannam@226
|
661 assert(frame->index < frame->node->n_vals);
|
cannam@226
|
662 return frame->node->vals[frame->index];
|
cannam@226
|
663 }
|
cannam@226
|
664
|
cannam@226
|
665 ZIX_API ZixBTreeIter*
|
cannam@226
|
666 zix_btree_begin(const ZixBTree* const t)
|
cannam@226
|
667 {
|
cannam@226
|
668 ZixBTreeIter* const i = zix_btree_iter_new(t);
|
cannam@226
|
669 if (!i) {
|
cannam@226
|
670 return NULL;
|
cannam@226
|
671 } else if (t->size == 0) {
|
cannam@226
|
672 i->stack[0].node = NULL;
|
cannam@226
|
673 } else {
|
cannam@226
|
674 ZixBTreeNode* n = t->root;
|
cannam@226
|
675 i->stack[0].node = n;
|
cannam@226
|
676 i->stack[0].index = 0;
|
cannam@226
|
677 while (!n->is_leaf) {
|
cannam@226
|
678 n = n->children[0];
|
cannam@226
|
679 ++i->level;
|
cannam@226
|
680 i->stack[i->level].node = n;
|
cannam@226
|
681 i->stack[i->level].index = 0;
|
cannam@226
|
682 }
|
cannam@226
|
683 }
|
cannam@226
|
684 return i;
|
cannam@226
|
685 }
|
cannam@226
|
686
|
cannam@226
|
687 ZIX_API bool
|
cannam@226
|
688 zix_btree_iter_is_end(const ZixBTreeIter* const i)
|
cannam@226
|
689 {
|
cannam@226
|
690 return !i || i->stack[0].node == NULL;
|
cannam@226
|
691 }
|
cannam@226
|
692
|
cannam@226
|
693 ZIX_API void
|
cannam@226
|
694 zix_btree_iter_increment(ZixBTreeIter* const i)
|
cannam@226
|
695 {
|
cannam@226
|
696 ZixBTreeIterFrame* f = &i->stack[i->level];
|
cannam@226
|
697 if (f->node->is_leaf) {
|
cannam@226
|
698 // Leaf, move right
|
cannam@226
|
699 assert(f->index < f->node->n_vals);
|
cannam@226
|
700 if (++f->index == f->node->n_vals) {
|
cannam@226
|
701 // Reached end of leaf, move up
|
cannam@226
|
702 f = &i->stack[i->level];
|
cannam@226
|
703 while (i->level > 0 && f->index == f->node->n_vals) {
|
cannam@226
|
704 f = &i->stack[--i->level];
|
cannam@226
|
705 assert(f->index <= f->node->n_vals);
|
cannam@226
|
706 }
|
cannam@226
|
707
|
cannam@226
|
708 if (f->index == f->node->n_vals) {
|
cannam@226
|
709 // Reached end of tree
|
cannam@226
|
710 assert(i->level == 0);
|
cannam@226
|
711 f->node = NULL;
|
cannam@226
|
712 f->index = 0;
|
cannam@226
|
713 }
|
cannam@226
|
714 }
|
cannam@226
|
715 } else {
|
cannam@226
|
716 // Internal node, move down to next child
|
cannam@226
|
717 assert(f->index < f->node->n_vals);
|
cannam@226
|
718 ZixBTreeNode* child = f->node->children[++f->index];
|
cannam@226
|
719
|
cannam@226
|
720 f = &i->stack[++i->level];
|
cannam@226
|
721 f->node = child;
|
cannam@226
|
722 f->index = 0;
|
cannam@226
|
723
|
cannam@226
|
724 // Move down and left until we hit a leaf
|
cannam@226
|
725 while (!f->node->is_leaf) {
|
cannam@226
|
726 child = f->node->children[0];
|
cannam@226
|
727 f = &i->stack[++i->level];
|
cannam@226
|
728 f->node = child;
|
cannam@226
|
729 f->index = 0;
|
cannam@226
|
730 }
|
cannam@226
|
731 }
|
cannam@226
|
732 }
|
cannam@226
|
733
|
cannam@226
|
734 ZIX_API void
|
cannam@226
|
735 zix_btree_iter_free(ZixBTreeIter* const i)
|
cannam@226
|
736 {
|
cannam@226
|
737 free(i);
|
cannam@226
|
738 }
|