00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include <stdio.h>
00033 #include <stdlib.h>
00034 #include <assert.h>
00035
00036 #include "tree234.h"
00037 #include "../../mem/shm_mem.h"
00038
00039
00040
00041 #define smalloc shm_malloc
00042 #define sfree shm_free
00043
00044 #define mknew(typ) ( (typ *) smalloc (sizeof (typ)) )
00045
00046 #ifdef TEST
00047 #define LOG123(x) (printf x)
00048 #else
00049 #define LOG123(x)
00050 #endif
00051
00052 typedef struct node234_Tag node234;
00053
00054 struct tree234_Tag {
00055 node234 *root;
00056 cmpfn234 cmp;
00057 };
00058
00059 struct node234_Tag {
00060 node234 *parent;
00061 node234 *kids[4];
00062 int counts[4];
00063 void *elems[3];
00064 };
00065
00066
00067
00068
00069 tree234 *newtree234(cmpfn234 cmp) {
00070 tree234 *ret = mknew(tree234);
00071 LOG123(("created tree %p\n", ret));
00072 ret->root = NULL;
00073 ret->cmp = cmp;
00074 return ret;
00075 }
00076
00077
00078
00079
00080 static void freenode234(node234 *n) {
00081 if (!n)
00082 return;
00083 freenode234(n->kids[0]);
00084 freenode234(n->kids[1]);
00085 freenode234(n->kids[2]);
00086 freenode234(n->kids[3]);
00087 sfree(n);
00088 }
00089 void freetree234(tree234 *t)
00090 {
00091 if(t == NULL)
00092 return;
00093 freenode234(t->root);
00094 sfree(t);
00095 }
00096
00097
00098
00099
00100 static void free2node234(node234 *n, freefn fn )
00101 {
00102 if (!n)
00103 return;
00104 free2node234(n->kids[0], fn);
00105 free2node234(n->kids[1], fn);
00106 free2node234(n->kids[2], fn);
00107 free2node234(n->kids[3], fn);
00108 fn(n->elems[0]);
00109 fn(n->elems[1]);
00110 fn(n->elems[2]);
00111 sfree(n);
00112 }
00113 void free2tree234(tree234 *t, freefn fn)
00114 {
00115 if(t == NULL)
00116 return;
00117 free2node234(t->root, fn);
00118 sfree(t);
00119 }
00120
00121
00122
00123
00124
00125 static int countnode234(node234 *n) {
00126 int count = 0;
00127 int i;
00128 if (!n)
00129 return 0;
00130 for (i = 0; i < 4; i++)
00131 count += n->counts[i];
00132 for (i = 0; i < 3; i++)
00133 if (n->elems[i])
00134 count++;
00135 return count;
00136 }
00137
00138
00139
00140
00141 int count234(tree234 *t) {
00142 if (t->root)
00143 return countnode234(t->root);
00144 else
00145 return 0;
00146 }
00147
00148
00149
00150
00151
00152 static void *add234_internal(tree234 *t, void *e, int index) {
00153 node234 *n, **np, *left, *right;
00154 void *orig_e = e;
00155 int c, lcount, rcount;
00156
00157 LOG123(("adding node %p to tree %p\n", e, t));
00158 if (t->root == NULL) {
00159 t->root = mknew(node234);
00160 t->root->elems[1] = t->root->elems[2] = NULL;
00161 t->root->kids[0] = t->root->kids[1] = NULL;
00162 t->root->kids[2] = t->root->kids[3] = NULL;
00163 t->root->counts[0] = t->root->counts[1] = 0;
00164 t->root->counts[2] = t->root->counts[3] = 0;
00165 t->root->parent = NULL;
00166 t->root->elems[0] = e;
00167 LOG123((" created root %p\n", t->root));
00168 return orig_e;
00169 }
00170
00171 np = &t->root;
00172 n = *np;
00173
00174 while (*np) {
00175 int childnum;
00176 n = *np;
00177 LOG123((" node %p: %p/%d [%p] %p/%d [%p] %p/%d [%p] %p/%d\n",
00178 n,
00179 n->kids[0], n->counts[0], n->elems[0],
00180 n->kids[1], n->counts[1], n->elems[1],
00181 n->kids[2], n->counts[2], n->elems[2],
00182 n->kids[3], n->counts[3]));
00183 if (index >= 0) {
00184 if (!n->kids[0]) {
00185
00186
00187
00188
00189
00190
00191 childnum = index;
00192 } else {
00193
00194
00195
00196
00197
00198 do {
00199 if (index <= n->counts[0]) {
00200 childnum = 0;
00201 break;
00202 }
00203 index -= n->counts[0] + 1;
00204 if (index <= n->counts[1]) {
00205 childnum = 1;
00206 break;
00207 }
00208 index -= n->counts[1] + 1;
00209 if (index <= n->counts[2]) {
00210 childnum = 2;
00211 break;
00212 }
00213 index -= n->counts[2] + 1;
00214 if (index <= n->counts[3]) {
00215 childnum = 3;
00216 break;
00217 }
00218 return NULL;
00219 } while (0);
00220 }
00221 } else {
00222 if ((c = t->cmp(e, n->elems[0])) < 0)
00223 childnum = 0;
00224 else if (c == 0)
00225 return n->elems[0];
00226 else if (n->elems[1] == NULL || (c = t->cmp(e, n->elems[1])) < 0)
00227 childnum = 1;
00228 else if (c == 0)
00229 return n->elems[1];
00230 else if (n->elems[2] == NULL || (c = t->cmp(e, n->elems[2])) < 0)
00231 childnum = 2;
00232 else if (c == 0)
00233 return n->elems[2];
00234 else
00235 childnum = 3;
00236 }
00237 np = &n->kids[childnum];
00238 LOG123((" moving to child %d (%p)\n", childnum, *np));
00239 }
00240
00241
00242
00243
00244 left = NULL; lcount = 0;
00245 right = NULL; rcount = 0;
00246 while (n) {
00247 LOG123((" at %p: %p/%d [%p] %p/%d [%p] %p/%d [%p] %p/%d\n",
00248 n,
00249 n->kids[0], n->counts[0], n->elems[0],
00250 n->kids[1], n->counts[1], n->elems[1],
00251 n->kids[2], n->counts[2], n->elems[2],
00252 n->kids[3], n->counts[3]));
00253 LOG123((" need to insert %p/%d [%p] %p/%d at position %d\n",
00254 left, lcount, e, right, rcount, np - n->kids));
00255 if (n->elems[1] == NULL) {
00256
00257
00258
00259 if (np == &n->kids[0]) {
00260 LOG123((" inserting on left of 2-node\n"));
00261 n->kids[2] = n->kids[1]; n->counts[2] = n->counts[1];
00262 n->elems[1] = n->elems[0];
00263 n->kids[1] = right; n->counts[1] = rcount;
00264 n->elems[0] = e;
00265 n->kids[0] = left; n->counts[0] = lcount;
00266 } else {
00267 LOG123((" inserting on right of 2-node\n"));
00268 n->kids[2] = right; n->counts[2] = rcount;
00269 n->elems[1] = e;
00270 n->kids[1] = left; n->counts[1] = lcount;
00271 }
00272 if (n->kids[0]) n->kids[0]->parent = n;
00273 if (n->kids[1]) n->kids[1]->parent = n;
00274 if (n->kids[2]) n->kids[2]->parent = n;
00275 LOG123((" done\n"));
00276 break;
00277 } else if (n->elems[2] == NULL) {
00278
00279
00280
00281 if (np == &n->kids[0]) {
00282 LOG123((" inserting on left of 3-node\n"));
00283 n->kids[3] = n->kids[2]; n->counts[3] = n->counts[2];
00284 n->elems[2] = n->elems[1];
00285 n->kids[2] = n->kids[1]; n->counts[2] = n->counts[1];
00286 n->elems[1] = n->elems[0];
00287 n->kids[1] = right; n->counts[1] = rcount;
00288 n->elems[0] = e;
00289 n->kids[0] = left; n->counts[0] = lcount;
00290 } else if (np == &n->kids[1]) {
00291 LOG123((" inserting in middle of 3-node\n"));
00292 n->kids[3] = n->kids[2]; n->counts[3] = n->counts[2];
00293 n->elems[2] = n->elems[1];
00294 n->kids[2] = right; n->counts[2] = rcount;
00295 n->elems[1] = e;
00296 n->kids[1] = left; n->counts[1] = lcount;
00297 } else {
00298 LOG123((" inserting on right of 3-node\n"));
00299 n->kids[3] = right; n->counts[3] = rcount;
00300 n->elems[2] = e;
00301 n->kids[2] = left; n->counts[2] = lcount;
00302 }
00303 if (n->kids[0]) n->kids[0]->parent = n;
00304 if (n->kids[1]) n->kids[1]->parent = n;
00305 if (n->kids[2]) n->kids[2]->parent = n;
00306 if (n->kids[3]) n->kids[3]->parent = n;
00307 LOG123((" done\n"));
00308 break;
00309 } else {
00310 node234 *m = mknew(node234);
00311 m->parent = n->parent;
00312 LOG123((" splitting a 4-node; created new node %p\n", m));
00313
00314
00315
00316
00317
00318
00319
00320
00321 if (np == &n->kids[0]) {
00322 m->kids[0] = left; m->counts[0] = lcount;
00323 m->elems[0] = e;
00324 m->kids[1] = right; m->counts[1] = rcount;
00325 m->elems[1] = n->elems[0];
00326 m->kids[2] = n->kids[1]; m->counts[2] = n->counts[1];
00327 e = n->elems[1];
00328 n->kids[0] = n->kids[2]; n->counts[0] = n->counts[2];
00329 n->elems[0] = n->elems[2];
00330 n->kids[1] = n->kids[3]; n->counts[1] = n->counts[3];
00331 } else if (np == &n->kids[1]) {
00332 m->kids[0] = n->kids[0]; m->counts[0] = n->counts[0];
00333 m->elems[0] = n->elems[0];
00334 m->kids[1] = left; m->counts[1] = lcount;
00335 m->elems[1] = e;
00336 m->kids[2] = right; m->counts[2] = rcount;
00337 e = n->elems[1];
00338 n->kids[0] = n->kids[2]; n->counts[0] = n->counts[2];
00339 n->elems[0] = n->elems[2];
00340 n->kids[1] = n->kids[3]; n->counts[1] = n->counts[3];
00341 } else if (np == &n->kids[2]) {
00342 m->kids[0] = n->kids[0]; m->counts[0] = n->counts[0];
00343 m->elems[0] = n->elems[0];
00344 m->kids[1] = n->kids[1]; m->counts[1] = n->counts[1];
00345 m->elems[1] = n->elems[1];
00346 m->kids[2] = left; m->counts[2] = lcount;
00347
00348 n->kids[0] = right; n->counts[0] = rcount;
00349 n->elems[0] = n->elems[2];
00350 n->kids[1] = n->kids[3]; n->counts[1] = n->counts[3];
00351 } else {
00352 m->kids[0] = n->kids[0]; m->counts[0] = n->counts[0];
00353 m->elems[0] = n->elems[0];
00354 m->kids[1] = n->kids[1]; m->counts[1] = n->counts[1];
00355 m->elems[1] = n->elems[1];
00356 m->kids[2] = n->kids[2]; m->counts[2] = n->counts[2];
00357 n->kids[0] = left; n->counts[0] = lcount;
00358 n->elems[0] = e;
00359 n->kids[1] = right; n->counts[1] = rcount;
00360 e = n->elems[2];
00361 }
00362 m->kids[3] = n->kids[3] = n->kids[2] = NULL;
00363 m->counts[3] = n->counts[3] = n->counts[2] = 0;
00364 m->elems[2] = n->elems[2] = n->elems[1] = NULL;
00365 if (m->kids[0]) m->kids[0]->parent = m;
00366 if (m->kids[1]) m->kids[1]->parent = m;
00367 if (m->kids[2]) m->kids[2]->parent = m;
00368 if (n->kids[0]) n->kids[0]->parent = n;
00369 if (n->kids[1]) n->kids[1]->parent = n;
00370 LOG123((" left (%p): %p/%d [%p] %p/%d [%p] %p/%d\n", m,
00371 m->kids[0], m->counts[0], m->elems[0],
00372 m->kids[1], m->counts[1], m->elems[1],
00373 m->kids[2], m->counts[2]));
00374 LOG123((" right (%p): %p/%d [%p] %p/%d\n", n,
00375 n->kids[0], n->counts[0], n->elems[0],
00376 n->kids[1], n->counts[1]));
00377 left = m; lcount = countnode234(left);
00378 right = n; rcount = countnode234(right);
00379 }
00380 if (n->parent)
00381 np = (n->parent->kids[0] == n ? &n->parent->kids[0] :
00382 n->parent->kids[1] == n ? &n->parent->kids[1] :
00383 n->parent->kids[2] == n ? &n->parent->kids[2] :
00384 &n->parent->kids[3]);
00385 n = n->parent;
00386 }
00387
00388
00389
00390
00391
00392
00393
00394 if (n) {
00395 while (n->parent) {
00396 int count = countnode234(n);
00397 int childnum;
00398 childnum = (n->parent->kids[0] == n ? 0 :
00399 n->parent->kids[1] == n ? 1 :
00400 n->parent->kids[2] == n ? 2 : 3);
00401 n->parent->counts[childnum] = count;
00402 n = n->parent;
00403 }
00404 } else {
00405 LOG123((" root is overloaded, split into two\n"));
00406 t->root = mknew(node234);
00407 t->root->kids[0] = left; t->root->counts[0] = lcount;
00408 t->root->elems[0] = e;
00409 t->root->kids[1] = right; t->root->counts[1] = rcount;
00410 t->root->elems[1] = NULL;
00411 t->root->kids[2] = NULL; t->root->counts[2] = 0;
00412 t->root->elems[2] = NULL;
00413 t->root->kids[3] = NULL; t->root->counts[3] = 0;
00414 t->root->parent = NULL;
00415 if (t->root->kids[0]) t->root->kids[0]->parent = t->root;
00416 if (t->root->kids[1]) t->root->kids[1]->parent = t->root;
00417 LOG123((" new root is %p/%d [%p] %p/%d\n",
00418 t->root->kids[0], t->root->counts[0],
00419 t->root->elems[0],
00420 t->root->kids[1], t->root->counts[1]));
00421 }
00422
00423 return orig_e;
00424 }
00425
00426 void *add234(tree234 *t, void *e) {
00427 if (!t->cmp)
00428 return NULL;
00429
00430 return add234_internal(t, e, -1);
00431 }
00432 void *addpos234(tree234 *t, void *e, int index) {
00433 if (index < 0 ||
00434 t->cmp)
00435 return NULL;
00436
00437 return add234_internal(t, e, index);
00438 }
00439
00440
00441
00442
00443
00444 void *index234(tree234 *t, int index) {
00445 node234 *n;
00446
00447 if (!t->root)
00448 return NULL;
00449
00450 if (index < 0 || index >= countnode234(t->root))
00451 return NULL;
00452
00453 n = t->root;
00454
00455 while (n) {
00456 if (index < n->counts[0])
00457 n = n->kids[0];
00458 else if (index -= n->counts[0] + 1, index < 0)
00459 return n->elems[0];
00460 else if (index < n->counts[1])
00461 n = n->kids[1];
00462 else if (index -= n->counts[1] + 1, index < 0)
00463 return n->elems[1];
00464 else if (index < n->counts[2])
00465 n = n->kids[2];
00466 else if (index -= n->counts[2] + 1, index < 0)
00467 return n->elems[2];
00468 else
00469 n = n->kids[3];
00470 }
00471
00472
00473 return NULL;
00474 }
00475
00476
00477
00478
00479
00480
00481
00482
00483 void *findrelpos234(tree234 *t, void *e, cmpfn234 cmp,
00484 int relation, int *index) {
00485 node234 *n;
00486 void *ret;
00487 int c;
00488 int idx, ecount, kcount, cmpret;
00489
00490 if (t->root == NULL)
00491 return NULL;
00492
00493 if (cmp == NULL)
00494 cmp = t->cmp;
00495
00496 n = t->root;
00497
00498
00499
00500 idx = 0;
00501 ecount = -1;
00502
00503
00504
00505 cmpret = 0;
00506 if (e == NULL) {
00507 assert(relation == REL234_LT || relation == REL234_GT);
00508 if (relation == REL234_LT)
00509 cmpret = +1;
00510 else if (relation == REL234_GT)
00511 cmpret = -1;
00512 }
00513 while (1) {
00514 for (kcount = 0; kcount < 4; kcount++) {
00515 if (kcount >= 3 || n->elems[kcount] == NULL ||
00516 (c = cmpret ? cmpret : cmp(e, n->elems[kcount])) < 0) {
00517 break;
00518 }
00519 if (n->kids[kcount]) idx += n->counts[kcount];
00520 if (c == 0) {
00521 ecount = kcount;
00522 break;
00523 }
00524 idx++;
00525 }
00526 if (ecount >= 0)
00527 break;
00528 if (n->kids[kcount])
00529 n = n->kids[kcount];
00530 else
00531 break;
00532 }
00533
00534 if (ecount >= 0) {
00535
00536
00537
00538
00539
00540 if (relation != REL234_LT && relation != REL234_GT) {
00541 if (index) *index = idx;
00542 return n->elems[ecount];
00543 }
00544
00545
00546
00547
00548
00549
00550
00551 if (relation == REL234_LT)
00552 idx--;
00553 else
00554 idx++;
00555 } else {
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565 if (relation == REL234_EQ)
00566 return NULL;
00567
00568
00569
00570
00571
00572
00573 if (relation == REL234_LT || relation == REL234_LE) {
00574 idx--;
00575 }
00576 }
00577
00578
00579
00580
00581
00582
00583 ret = index234(t, idx);
00584 if (ret && index) *index = idx;
00585 return ret;
00586 }
00587 void *find234(tree234 *t, void *e, cmpfn234 cmp) {
00588 return findrelpos234(t, e, cmp, REL234_EQ, NULL);
00589 }
00590 void *findrel234(tree234 *t, void *e, cmpfn234 cmp, int relation) {
00591 return findrelpos234(t, e, cmp, relation, NULL);
00592 }
00593 void *findpos234(tree234 *t, void *e, cmpfn234 cmp, int *index) {
00594 return findrelpos234(t, e, cmp, REL234_EQ, index);
00595 }
00596
00597
00598
00599
00600
00601 static void *delpos234_internal(tree234 *t, int index) {
00602 node234 *n;
00603 void *retval;
00604 int ei = -1;
00605
00606 retval = 0;
00607
00608 n = t->root;
00609 LOG123(("deleting item %d from tree %p\n", index, t));
00610 while (1) {
00611 while (n) {
00612 int ki;
00613 node234 *sub;
00614
00615 LOG123((" node %p: %p/%d [%p] %p/%d [%p] %p/%d [%p] %p/%d index=%d\n",
00616 n,
00617 n->kids[0], n->counts[0], n->elems[0],
00618 n->kids[1], n->counts[1], n->elems[1],
00619 n->kids[2], n->counts[2], n->elems[2],
00620 n->kids[3], n->counts[3],
00621 index));
00622 if (index < n->counts[0]) {
00623 ki = 0;
00624 } else if (index -= n->counts[0]+1, index < 0) {
00625 ei = 0; break;
00626 } else if (index < n->counts[1]) {
00627 ki = 1;
00628 } else if (index -= n->counts[1]+1, index < 0) {
00629 ei = 1; break;
00630 } else if (index < n->counts[2]) {
00631 ki = 2;
00632 } else if (index -= n->counts[2]+1, index < 0) {
00633 ei = 2; break;
00634 } else {
00635 ki = 3;
00636 }
00637
00638
00639
00640
00641 LOG123((" moving to subtree %d\n", ki));
00642 sub = n->kids[ki];
00643 if (!sub->elems[1]) {
00644 LOG123((" subtree has only one element!\n", ki));
00645 if (ki > 0 && n->kids[ki-1]->elems[1]) {
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656 node234 *sib = n->kids[ki-1];
00657 int lastelem = (sib->elems[2] ? 2 :
00658 sib->elems[1] ? 1 : 0);
00659 sub->kids[2] = sub->kids[1];
00660 sub->counts[2] = sub->counts[1];
00661 sub->elems[1] = sub->elems[0];
00662 sub->kids[1] = sub->kids[0];
00663 sub->counts[1] = sub->counts[0];
00664 sub->elems[0] = n->elems[ki-1];
00665 sub->kids[0] = sib->kids[lastelem+1];
00666 sub->counts[0] = sib->counts[lastelem+1];
00667 if (sub->kids[0]) sub->kids[0]->parent = sub;
00668 n->elems[ki-1] = sib->elems[lastelem];
00669 sib->kids[lastelem+1] = NULL;
00670 sib->counts[lastelem+1] = 0;
00671 sib->elems[lastelem] = NULL;
00672 n->counts[ki] = countnode234(sub);
00673 LOG123((" case 3a left\n"));
00674 LOG123((" index and left subtree count before adjustment: %d, %d\n",
00675 index, n->counts[ki-1]));
00676 index += n->counts[ki-1];
00677 n->counts[ki-1] = countnode234(sib);
00678 index -= n->counts[ki-1];
00679 LOG123((" index and left subtree count after adjustment: %d, %d\n",
00680 index, n->counts[ki-1]));
00681 } else if (ki < 3 && n->kids[ki+1] &&
00682 n->kids[ki+1]->elems[1]) {
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692 node234 *sib = n->kids[ki+1];
00693 int j;
00694 sub->elems[1] = n->elems[ki];
00695 sub->kids[2] = sib->kids[0];
00696 sub->counts[2] = sib->counts[0];
00697 if (sub->kids[2]) sub->kids[2]->parent = sub;
00698 n->elems[ki] = sib->elems[0];
00699 sib->kids[0] = sib->kids[1];
00700 sib->counts[0] = sib->counts[1];
00701 for (j = 0; j < 2 && sib->elems[j+1]; j++) {
00702 sib->kids[j+1] = sib->kids[j+2];
00703 sib->counts[j+1] = sib->counts[j+2];
00704 sib->elems[j] = sib->elems[j+1];
00705 }
00706 sib->kids[j+1] = NULL;
00707 sib->counts[j+1] = 0;
00708 sib->elems[j] = NULL;
00709 n->counts[ki] = countnode234(sub);
00710 n->counts[ki+1] = countnode234(sib);
00711 LOG123((" case 3a right\n"));
00712 } else {
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732 node234 *sib;
00733 int j;
00734
00735 if (ki > 0) {
00736 ki--;
00737 index += n->counts[ki] + 1;
00738 }
00739 sib = n->kids[ki];
00740 sub = n->kids[ki+1];
00741
00742 sub->kids[3] = sub->kids[1];
00743 sub->counts[3] = sub->counts[1];
00744 sub->elems[2] = sub->elems[0];
00745 sub->kids[2] = sub->kids[0];
00746 sub->counts[2] = sub->counts[0];
00747 sub->elems[1] = n->elems[ki];
00748 sub->kids[1] = sib->kids[1];
00749 sub->counts[1] = sib->counts[1];
00750 if (sub->kids[1]) sub->kids[1]->parent = sub;
00751 sub->elems[0] = sib->elems[0];
00752 sub->kids[0] = sib->kids[0];
00753 sub->counts[0] = sib->counts[0];
00754 if (sub->kids[0]) sub->kids[0]->parent = sub;
00755
00756 n->counts[ki+1] = countnode234(sub);
00757
00758 sfree(sib);
00759
00760
00761
00762
00763
00764 for (j = ki; j < 3 && n->kids[j+1]; j++) {
00765 n->kids[j] = n->kids[j+1];
00766 n->counts[j] = n->counts[j+1];
00767 n->elems[j] = j<2 ? n->elems[j+1] : NULL;
00768 }
00769 n->kids[j] = NULL;
00770 n->counts[j] = 0;
00771 if (j < 3) n->elems[j] = NULL;
00772 LOG123((" case 3b ki=%d\n", ki));
00773
00774 if (!n->elems[0]) {
00775
00776
00777
00778
00779 LOG123((" shifting root!\n"));
00780 t->root = sub;
00781 sub->parent = NULL;
00782 sfree(n);
00783 }
00784 }
00785 }
00786 n = sub;
00787 }
00788 if (!retval)
00789 retval = n->elems[ei];
00790
00791 if (ei==-1)
00792 return NULL;
00793
00794
00795
00796
00797
00798
00799 if (!n->parent && !n->elems[1] && !n->kids[0]) {
00800 LOG123((" removed last element in tree\n"));
00801 sfree(n);
00802 t->root = NULL;
00803 return retval;
00804 }
00805
00806
00807
00808
00809
00810
00811
00812 if (!n->kids[0] && n->elems[1]) {
00813
00814
00815
00816
00817
00818 int i;
00819 LOG123((" case 1\n"));
00820 for (i = ei; i < 2 && n->elems[i+1]; i++)
00821 n->elems[i] = n->elems[i+1];
00822 n->elems[i] = NULL;
00823
00824
00825
00826
00827 while (n->parent) {
00828 int childnum;
00829 childnum = (n->parent->kids[0] == n ? 0 :
00830 n->parent->kids[1] == n ? 1 :
00831 n->parent->kids[2] == n ? 2 : 3);
00832 n->parent->counts[childnum]--;
00833 n = n->parent;
00834 }
00835 return retval;
00836 } else if (n->kids[ei]->elems[1]) {
00837
00838
00839
00840
00841
00842
00843
00844
00845 node234 *m = n->kids[ei];
00846 void *target;
00847 LOG123((" case 2a\n"));
00848 while (m->kids[0]) {
00849 m = (m->kids[3] ? m->kids[3] :
00850 m->kids[2] ? m->kids[2] :
00851 m->kids[1] ? m->kids[1] : m->kids[0]);
00852 }
00853 target = (m->elems[2] ? m->elems[2] :
00854 m->elems[1] ? m->elems[1] : m->elems[0]);
00855 n->elems[ei] = target;
00856 index = n->counts[ei]-1;
00857 n = n->kids[ei];
00858 } else if (n->kids[ei+1]->elems[1]) {
00859
00860
00861
00862
00863 node234 *m = n->kids[ei+1];
00864 void *target;
00865 LOG123((" case 2b\n"));
00866 while (m->kids[0]) {
00867 m = m->kids[0];
00868 }
00869 target = m->elems[0];
00870 n->elems[ei] = target;
00871 n = n->kids[ei+1];
00872 index = 0;
00873 } else {
00874
00875
00876
00877
00878
00879
00880
00881
00882 node234 *a = n->kids[ei], *b = n->kids[ei+1];
00883 int j;
00884
00885 LOG123((" case 2c\n"));
00886 a->elems[1] = n->elems[ei];
00887 a->kids[2] = b->kids[0];
00888 a->counts[2] = b->counts[0];
00889 if (a->kids[2]) a->kids[2]->parent = a;
00890 a->elems[2] = b->elems[0];
00891 a->kids[3] = b->kids[1];
00892 a->counts[3] = b->counts[1];
00893 if (a->kids[3]) a->kids[3]->parent = a;
00894 sfree(b);
00895 n->counts[ei] = countnode234(a);
00896
00897
00898
00899
00900 for (j = ei; j < 2 && n->elems[j+1]; j++) {
00901 n->elems[j] = n->elems[j+1];
00902 n->kids[j+1] = n->kids[j+2];
00903 n->counts[j+1] = n->counts[j+2];
00904 }
00905 n->elems[j] = NULL;
00906 n->kids[j+1] = NULL;
00907 n->counts[j+1] = 0;
00908
00909
00910
00911
00912
00913 if (n->elems[0] == NULL) {
00914 LOG123((" shifting root!\n"));
00915 t->root = a;
00916 a->parent = NULL;
00917 sfree(n);
00918 }
00919
00920
00921
00922
00923 n = a;
00924 index = a->counts[0] + a->counts[1] + 1;
00925 }
00926 }
00927 }
00928 void *delpos234(tree234 *t, int index) {
00929 if (index < 0 || index >= countnode234(t->root))
00930 return NULL;
00931 return delpos234_internal(t, index);
00932 }
00933 void *del234(tree234 *t, void *e) {
00934 int index;
00935 if (!findrelpos234(t, e, NULL, REL234_EQ, &index))
00936 return NULL;
00937 return delpos234_internal(t, index);
00938 }
00939
00940 #ifdef TEST
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965 #include <stdarg.h>
00966
00967 #define srealloc realloc
00968
00969
00970
00971
00972 void error(char *fmt, ...) {
00973 va_list ap;
00974 printf("ERROR: ");
00975 va_start(ap, fmt);
00976 vfprintf(stdout, fmt, ap);
00977 va_end(ap);
00978 printf("\n");
00979 }
00980
00981
00982 void **array;
00983 int arraylen, arraysize;
00984 cmpfn234 cmp;
00985
00986
00987 tree234 *tree;
00988
00989 typedef struct {
00990 int treedepth;
00991 int elemcount;
00992 } chkctx;
00993
00994 int chknode(chkctx *ctx, int level, node234 *node,
00995 void *lowbound, void *highbound) {
00996 int nkids, nelems;
00997 int i;
00998 int count;
00999
01000
01001 for (nkids = 0; nkids < 4 && node->kids[nkids]; nkids++);
01002
01003 for (i = nkids; i < 4; i++)
01004 if (node->kids[i]) {
01005 error("node %p: nkids=%d but kids[%d] non-NULL",
01006 node, nkids, i);
01007 } else if (node->counts[i]) {
01008 error("node %p: kids[%d] NULL but count[%d]=%d nonzero",
01009 node, i, i, node->counts[i]);
01010 }
01011
01012
01013 for (nelems = 0; nelems < 3 && node->elems[nelems]; nelems++);
01014
01015 for (i = nelems; i < 3; i++)
01016 if (node->elems[i]) {
01017 error("node %p: nelems=%d but elems[%d] non-NULL",
01018 node, nelems, i);
01019 }
01020
01021 if (nkids == 0) {
01022
01023
01024
01025
01026 if (ctx->treedepth < 0)
01027 ctx->treedepth = level;
01028 else if (ctx->treedepth != level)
01029 error("node %p: leaf at depth %d, previously seen depth %d",
01030 node, level, ctx->treedepth);
01031 } else {
01032
01033
01034
01035
01036
01037 int shouldkids = (nelems ? nelems+1 : 0);
01038 if (nkids != shouldkids) {
01039 error("node %p: %d elems should mean %d kids but has %d",
01040 node, nelems, shouldkids, nkids);
01041 }
01042 }
01043
01044
01045
01046
01047 if (nelems == 0) {
01048 error("node %p: no elems", node, nkids);
01049 }
01050
01051
01052
01053
01054 ctx->elemcount += nelems;
01055
01056
01057
01058
01059
01060
01061
01062
01063 if (cmp) {
01064 for (i = -1; i < nelems; i++) {
01065 void *lower = (i == -1 ? lowbound : node->elems[i]);
01066 void *higher = (i+1 == nelems ? highbound : node->elems[i+1]);
01067 if (lower && higher && cmp(lower, higher) >= 0) {
01068 error("node %p: kid comparison [%d=%s,%d=%s] failed",
01069 node, i, lower, i+1, higher);
01070 }
01071 }
01072 }
01073
01074
01075
01076
01077
01078 for (i = 0; i < nkids; i++)
01079 if (node->kids[i]->parent != node) {
01080 error("node %p kid %d: parent ptr is %p not %p",
01081 node, i, node->kids[i]->parent, node);
01082 }
01083
01084
01085
01086
01087
01088 count = nelems;
01089
01090 for (i = 0; i < nkids; i++) {
01091 void *lower = (i == 0 ? lowbound : node->elems[i-1]);
01092 void *higher = (i >= nelems ? highbound : node->elems[i]);
01093 int subcount = chknode(ctx, level+1, node->kids[i], lower, higher);
01094 if (node->counts[i] != subcount) {
01095 error("node %p kid %d: count says %d, subtree really has %d",
01096 node, i, node->counts[i], subcount);
01097 }
01098 count += subcount;
01099 }
01100
01101 return count;
01102 }
01103
01104 void verify(void) {
01105 chkctx ctx;
01106 int i;
01107 void *p;
01108
01109 ctx.treedepth = -1;
01110 ctx.elemcount = 0;
01111
01112
01113
01114 if (tree->root) {
01115 if (tree->root->parent != NULL)
01116 error("root->parent is %p should be null", tree->root->parent);
01117 chknode(&ctx, 0, tree->root, NULL, NULL);
01118 }
01119 printf("tree depth: %d\n", ctx.treedepth);
01120
01121
01122
01123 for (i = 0; NULL != (p = index234(tree, i)); i++) {
01124 if (i >= arraylen)
01125 error("tree contains more than %d elements", arraylen);
01126 if (array[i] != p)
01127 error("enum at position %d: array says %s, tree says %s",
01128 i, array[i], p);
01129 }
01130 if (ctx.elemcount != i) {
01131 error("tree really contains %d elements, enum gave %d",
01132 ctx.elemcount, i);
01133 }
01134 if (i < arraylen) {
01135 error("enum gave only %d elements, array has %d", i, arraylen);
01136 }
01137 i = count234(tree);
01138 if (ctx.elemcount != i) {
01139 error("tree really contains %d elements, count234 gave %d",
01140 ctx.elemcount, i);
01141 }
01142 }
01143
01144 void internal_addtest(void *elem, int index, void *realret) {
01145 int i, j;
01146 void *retval;
01147
01148 if (arraysize < arraylen+1) {
01149 arraysize = arraylen+1+256;
01150 array = (array == NULL ? smalloc(arraysize*sizeof(*array)) :
01151 srealloc(array, arraysize*sizeof(*array)));
01152 }
01153
01154 i = index;
01155
01156 retval = elem;
01157 for (j = arraylen; j > i; j--)
01158 array[j] = array[j-1];
01159 array[i] = elem;
01160 arraylen++;
01161
01162 if (realret != retval) {
01163 error("add: retval was %p expected %p", realret, retval);
01164 }
01165
01166 verify();
01167 }
01168
01169 void addtest(void *elem) {
01170 int i;
01171 void *realret;
01172
01173 realret = add234(tree, elem);
01174
01175 i = 0;
01176 while (i < arraylen && cmp(elem, array[i]) > 0)
01177 i++;
01178 if (i < arraylen && !cmp(elem, array[i])) {
01179 void *retval = array[i];
01180 if (realret != retval) {
01181 error("add: retval was %p expected %p", realret, retval);
01182 }
01183 } else
01184 internal_addtest(elem, i, realret);
01185 }
01186
01187 void addpostest(void *elem, int i) {
01188 void *realret;
01189
01190 realret = addpos234(tree, elem, i);
01191
01192 internal_addtest(elem, i, realret);
01193 }
01194
01195 void delpostest(int i) {
01196 int index = i;
01197 void *elem = array[i], *ret;
01198
01199
01200 while (i < arraylen-1) {
01201 array[i] = array[i+1];
01202 i++;
01203 }
01204 arraylen--;
01205
01206 if (tree->cmp)
01207 ret = del234(tree, elem);
01208 else
01209 ret = delpos234(tree, index);
01210
01211 if (ret != elem) {
01212 error("del returned %p, expected %p", ret, elem);
01213 }
01214
01215 verify();
01216 }
01217
01218 void deltest(void *elem) {
01219 int i;
01220
01221 i = 0;
01222 while (i < arraylen && cmp(elem, array[i]) > 0)
01223 i++;
01224 if (i >= arraylen || cmp(elem, array[i]) != 0)
01225 return;
01226 delpostest(i);
01227 }
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237 int randomnumber(unsigned *seed) {
01238 *seed *= 1103515245;
01239 *seed += 12345;
01240 return ((*seed) / 65536) % 32768;
01241 }
01242
01243 int mycmp(void *av, void *bv) {
01244 char const *a = (char const *)av;
01245 char const *b = (char const *)bv;
01246 return strcmp(a, b);
01247 }
01248
01249 #define lenof(x) ( sizeof((x)) / sizeof(*(x)) )
01250
01251 char *strings[] = {
01252 "a", "ab", "absque", "coram", "de",
01253 "palam", "clam", "cum", "ex", "e",
01254 "sine", "tenus", "pro", "prae",
01255 "banana", "carrot", "cabbage", "broccoli", "onion", "zebra",
01256 "penguin", "blancmange", "pangolin", "whale", "hedgehog",
01257 "giraffe", "peanut", "bungee", "foo", "bar", "baz", "quux",
01258 "murfl", "spoo", "breen", "flarn", "octothorpe",
01259 "snail", "tiger", "elephant", "octopus", "warthog", "armadillo",
01260 "aardvark", "wyvern", "dragon", "elf", "dwarf", "orc", "goblin",
01261 "pixie", "basilisk", "warg", "ape", "lizard", "newt", "shopkeeper",
01262 "wand", "ring", "amulet"
01263 };
01264
01265 #define NSTR lenof(strings)
01266
01267 int findtest(void) {
01268 const static int rels[] = {
01269 REL234_EQ, REL234_GE, REL234_LE, REL234_LT, REL234_GT
01270 };
01271 const static char *const relnames[] = {
01272 "EQ", "GE", "LE", "LT", "GT"
01273 };
01274 int i, j, rel, index;
01275 char *p, *ret, *realret, *realret2;
01276 int lo, hi, mid, c;
01277
01278 for (i = 0; i < NSTR; i++) {
01279 p = strings[i];
01280 for (j = 0; j < sizeof(rels)/sizeof(*rels); j++) {
01281 rel = rels[j];
01282
01283 lo = 0; hi = arraylen-1;
01284 while (lo <= hi) {
01285 mid = (lo + hi) / 2;
01286 c = strcmp(p, array[mid]);
01287 if (c < 0)
01288 hi = mid-1;
01289 else if (c > 0)
01290 lo = mid+1;
01291 else
01292 break;
01293 }
01294
01295 if (c == 0) {
01296 if (rel == REL234_LT)
01297 ret = (mid > 0 ? array[--mid] : NULL);
01298 else if (rel == REL234_GT)
01299 ret = (mid < arraylen-1 ? array[++mid] : NULL);
01300 else
01301 ret = array[mid];
01302 } else {
01303 assert(lo == hi+1);
01304 if (rel == REL234_LT || rel == REL234_LE) {
01305 mid = hi;
01306 ret = (hi >= 0 ? array[hi] : NULL);
01307 } else if (rel == REL234_GT || rel == REL234_GE) {
01308 mid = lo;
01309 ret = (lo < arraylen ? array[lo] : NULL);
01310 } else
01311 ret = NULL;
01312 }
01313
01314 realret = findrelpos234(tree, p, NULL, rel, &index);
01315 if (realret != ret) {
01316 error("find(\"%s\",%s) gave %s should be %s",
01317 p, relnames[j], realret, ret);
01318 }
01319 if (realret && index != mid) {
01320 error("find(\"%s\",%s) gave %d should be %d",
01321 p, relnames[j], index, mid);
01322 }
01323 if (realret && rel == REL234_EQ) {
01324 realret2 = index234(tree, index);
01325 if (realret2 != realret) {
01326 error("find(\"%s\",%s) gave %s(%d) but %d -> %s",
01327 p, relnames[j], realret, index, index, realret2);
01328 }
01329 }
01330 #if 0
01331 printf("find(\"%s\",%s) gave %s(%d)\n", p, relnames[j],
01332 realret, index);
01333 #endif
01334 }
01335 }
01336
01337 realret = findrelpos234(tree, NULL, NULL, REL234_GT, &index);
01338 if (arraylen && (realret != array[0] || index != 0)) {
01339 error("find(NULL,GT) gave %s(%d) should be %s(0)",
01340 realret, index, array[0]);
01341 } else if (!arraylen && (realret != NULL)) {
01342 error("find(NULL,GT) gave %s(%d) should be NULL",
01343 realret, index);
01344 }
01345
01346 realret = findrelpos234(tree, NULL, NULL, REL234_LT, &index);
01347 if (arraylen && (realret != array[arraylen-1] || index != arraylen-1)) {
01348 error("find(NULL,LT) gave %s(%d) should be %s(0)",
01349 realret, index, array[arraylen-1]);
01350 } else if (!arraylen && (realret != NULL)) {
01351 error("find(NULL,LT) gave %s(%d) should be NULL",
01352 realret, index);
01353 }
01354 }
01355
01356 int main(void) {
01357 int in[NSTR];
01358 int i, j, k;
01359 unsigned seed = 0;
01360
01361 for (i = 0; i < NSTR; i++) in[i] = 0;
01362 array = NULL;
01363 arraylen = arraysize = 0;
01364 tree = newtree234(mycmp);
01365 cmp = mycmp;
01366
01367 verify();
01368 for (i = 0; i < 10000; i++) {
01369 j = randomnumber(&seed);
01370 j %= NSTR;
01371 printf("trial: %d\n", i);
01372 if (in[j]) {
01373 printf("deleting %s (%d)\n", strings[j], j);
01374 deltest(strings[j]);
01375 in[j] = 0;
01376 } else {
01377 printf("adding %s (%d)\n", strings[j], j);
01378 addtest(strings[j]);
01379 in[j] = 1;
01380 }
01381 findtest();
01382 }
01383
01384 while (arraylen > 0) {
01385 j = randomnumber(&seed);
01386 j %= arraylen;
01387 deltest(array[j]);
01388 }
01389
01390 freetree234(tree);
01391
01392
01393
01394
01395
01396
01397
01398
01399 tree = newtree234(NULL);
01400 cmp = NULL;
01401 verify();
01402 for (i = 0; i < 1000; i++) {
01403 printf("trial: %d\n", i);
01404 j = randomnumber(&seed);
01405 j %= NSTR;
01406 k = randomnumber(&seed);
01407 k %= count234(tree)+1;
01408 printf("adding string %s at index %d\n", strings[j], k);
01409 addpostest(strings[j], k);
01410 }
01411 while (count234(tree) > 0) {
01412 printf("cleanup: tree size %d\n", count234(tree));
01413 j = randomnumber(&seed);
01414 j %= count234(tree);
01415 printf("deleting string %s from index %d\n", array[j], j);
01416 delpostest(j);
01417 }
01418
01419 return 0;
01420 }
01421
01422 #endif