00001
00002
00003
00004
00005
00006
00007
00008 #include "common.h"
00009 #include "localmem.h"
00010 #include "rbTree.h"
00011
00012 static char const rcsid[] = "$Id: rbTree.c,v 1.10 2007/02/24 15:59:29 kent Exp $";
00013
00014
00015 static struct rbTreeNode *restructure(struct rbTree *t, int tos,
00016 struct rbTreeNode *x, struct rbTreeNode *y, struct rbTreeNode *z)
00017
00018
00019
00020 {
00021 struct rbTreeNode *parent, *midNode;
00022
00023 if(y == x->left)
00024 {
00025 if(z == y->left)
00026 {
00027 midNode = y;
00028 y->left = z;
00029 x->left = y->right;
00030 y->right = x;
00031 }
00032 else
00033 {
00034 midNode = z;
00035 y->right = z->left;
00036 z->left = y;
00037 x->left = z->right;
00038 z->right = x;
00039 }
00040 }
00041 else
00042 {
00043 if(z == y->left)
00044 {
00045 midNode = z;
00046 x->right = z->left;
00047 z->left = x;
00048 y->left = z->right;
00049 z->right = y;
00050 }
00051 else
00052 {
00053 midNode = y;
00054 x->right = y->left;
00055 y->left = x;
00056 y->right = z;
00057 }
00058 }
00059 if(tos != 0)
00060 {
00061 parent = t->stack[tos-1];
00062 if(x == parent->left)
00063 parent->left = midNode;
00064 else
00065 parent->right = midNode;
00066 }
00067 else
00068 t->root = midNode;
00069
00070 return midNode;
00071 }
00072
00073 struct rbTree *rbTreeNewDetailed(int (*compare)(void *, void *), struct lm *lm,
00074 struct rbTreeNode *stack[128])
00075
00076
00077
00078 {
00079 struct rbTree *t;
00080 AllocVar(t);
00081 t->root = NULL;
00082 t->compare = compare;
00083 t->lm = lm;
00084 t->stack = stack;
00085 t->n = 0;
00086 return t;
00087 }
00088
00089 struct rbTree *rbTreeNew(int (*compare)(void *, void *))
00090
00091
00092
00093
00094 {
00095
00096
00097
00098
00099
00100
00101
00102
00103 struct lm *lm = lmInit(0);
00104 struct rbTreeNode **stack = lmAlloc(lm, 128 * sizeof(stack[0]));
00105 return rbTreeNewDetailed(compare, lm, stack);
00106 }
00107
00108
00109 void rbTreeFree(struct rbTree **pTree)
00110
00111 {
00112 struct rbTree *tree = *pTree;
00113 if (tree != NULL)
00114 {
00115 lmCleanup(&tree->lm);
00116 freez(pTree);
00117 }
00118 }
00119
00120
00121 void *rbTreeAdd(struct rbTree *t, void *item)
00122
00123
00124
00125
00126
00127
00128 {
00129 struct rbTreeNode *x, *p, *q, *m, **attachX;
00130 int (* compare)(void *, void *);
00131 int cmpResult;
00132 rbTreeColor col;
00133 struct rbTreeNode **stack = NULL;
00134 int tos;
00135
00136 tos = 0;
00137 if((p = t->root) != NULL)
00138 {
00139 compare = t->compare;
00140 stack = t->stack;
00141
00142
00143
00144
00145 for(;;)
00146 {
00147 stack[tos++] = p;
00148 cmpResult = compare(item, p->item);
00149 if(cmpResult < 0)
00150 {
00151 p = p->left;
00152 if(!p)
00153 {
00154 p = stack[--tos];
00155 attachX = &p->left;
00156 break;
00157 }
00158 }
00159 else if(cmpResult > 0)
00160 {
00161 p = p->right;
00162 if(!p)
00163 {
00164 p = stack[--tos];
00165 attachX = &p->right;
00166 break;
00167 }
00168 }
00169 else
00170 {
00171 return p->item;
00172 }
00173 }
00174 col = rbTreeRed;
00175 }
00176 else
00177 {
00178 attachX = &t->root;
00179 col = rbTreeBlack;
00180 }
00181
00182
00183 if ((x = t->freeList) != NULL)
00184 t->freeList = x->right;
00185 else
00186 lmAllocVar(t->lm, x);
00187 x->left = x->right = NULL;
00188 x->item = item;
00189 x->color = col;
00190 *attachX = x;
00191 t->n++;
00192
00193
00194
00195
00196 if(tos > 0)
00197 {
00198 while(p->color == rbTreeRed)
00199 {
00200
00201
00202 m = stack[--tos];
00203 q = p == m->left ? m->right : m->left;
00204
00205
00206 if(!q || q->color == rbTreeBlack)
00207 {
00208
00209
00210
00211
00212
00213 m = restructure(t, tos, m, p, x);
00214 m->color = rbTreeBlack;
00215 m->left->color = m->right->color = rbTreeRed;
00216
00217
00218 break;
00219 }
00220
00221
00222
00223 p->color = rbTreeBlack;
00224 q->color = rbTreeBlack;
00225
00226 if(tos == 0) break;
00227
00228 m->color = rbTreeRed;
00229
00230
00231 x = m;
00232 p = stack[--tos];
00233 }
00234 }
00235
00236 return NULL;
00237 }
00238
00239
00240 void *rbTreeFind(struct rbTree *t, void *item)
00241
00242
00243
00244
00245 {
00246 struct rbTreeNode *p, *nextP;
00247 int (*compare)(void *, void *) = t->compare;
00248 int cmpResult;
00249
00250
00251
00252 for (p = t->root; p != NULL; p = nextP)
00253 {
00254 cmpResult = compare(item, p->item);
00255 if(cmpResult < 0)
00256 nextP = p->left;
00257 else if(cmpResult > 0)
00258 nextP = p->right;
00259 else
00260 return p->item;
00261 }
00262 return NULL;
00263 }
00264
00265
00266 void *rbTreeRemove(struct rbTree *t, void *item)
00267
00268
00269
00270
00271 {
00272 struct rbTreeNode *p, *r, *x, *y, *z, *b, *newY;
00273 struct rbTreeNode *m;
00274 rbTreeColor removeCol;
00275 void *returnItem;
00276 int (* compare)(void *, void *);
00277 int cmpResult;
00278 struct rbTreeNode **stack;
00279 int i, tos;
00280
00281
00282
00283 if((p = t->root))
00284 {
00285 compare = t->compare;
00286 stack = t->stack;
00287 tos = 0;
00288
00289 for(;;)
00290 {
00291 stack[tos++] = p;
00292 cmpResult = compare(item, p->item);
00293 if(cmpResult < 0)
00294 p = p->left;
00295 else if(cmpResult > 0)
00296 p = p->right;
00297 else
00298
00299 break;
00300 if(!p) return NULL;
00301 }
00302 }
00303 else
00304 return NULL;
00305
00306
00307
00308
00309 if(!p->left)
00310 {
00311 tos--;
00312
00313 if(tos == 0)
00314 {
00315 r = t->root = p->right;
00316 x = y = NULL;
00317 }
00318 else
00319 {
00320 x = stack[--tos];
00321 if(p == x->left)
00322 {
00323 r = x->left = p->right;
00324 y = x->right;
00325 }
00326 else
00327 {
00328 r = x->right = p->right;
00329 y = x->left;
00330 }
00331 }
00332 removeCol = p->color;
00333 }
00334 else if(!p->right)
00335 {
00336 tos--;
00337
00338 if(tos == 0)
00339 {
00340 r = t->root = p->left;
00341 x = y = NULL;
00342 }
00343 else
00344 {
00345 x = stack[--tos];
00346 if(p == x->left)
00347 {
00348 r = x->left = p->left;
00349 y = x->right;
00350 }
00351 else
00352 {
00353 r = x->right = p->left;
00354 y = x->left;
00355 }
00356 }
00357 removeCol = p->color;
00358 }
00359 else
00360 {
00361
00362 i = tos-1;
00363
00364
00365 m = p->right;
00366 do
00367 {
00368 stack[tos++] = m;
00369 m = m->left;
00370 } while(m);
00371 m = stack[--tos];
00372
00373
00374 if(i == 0)
00375 {
00376 t->root = m;
00377 }
00378 else
00379 {
00380 x = stack[i-1];
00381 if(p == x->left)
00382 {
00383 x->left = m;
00384 }
00385 else
00386 {
00387 x->right = m;
00388 }
00389 }
00390
00391
00392
00393
00394 stack[i] = m;
00395 x = stack[--tos];
00396 r = m->right;
00397 if(tos != i)
00398 {
00399 y = x->right;
00400 x->left = r;
00401 m->right = p->right;
00402 }
00403 else
00404 {
00405 y = p->left;
00406 }
00407 m->left = p->left;
00408
00409
00410 removeCol = m->color;
00411 m->color = p->color;
00412 }
00413
00414
00415 returnItem = p->item;
00416 p->right = t->freeList;
00417 t->freeList = p;
00418
00419 t->n--;
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434 if(removeCol == rbTreeBlack)
00435 {
00436
00437
00438 if(!r || r->color == rbTreeBlack)
00439 {
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455 if(x) for(;;)
00456 {
00457
00458
00459
00460
00461
00462
00463 if(y->color == rbTreeBlack)
00464 {
00465
00466
00467 if(((z = y->left) && z->color == rbTreeRed) ||
00468 ((z = y->right) && z->color == rbTreeRed))
00469 {
00470
00471
00472
00473
00474 b = restructure(t, tos, x, y, z);
00475 b->color = x->color;
00476 b->left->color = b->right->color = rbTreeBlack;
00477
00478 break;
00479 }
00480 else
00481 {
00482
00483
00484 y->color = rbTreeRed;
00485
00486 if(x->color == rbTreeRed)
00487 {
00488 x->color = rbTreeBlack;
00489 break;
00490 }
00491
00492
00493 if(tos == 0) break;
00494
00495
00496 r = x;
00497 x = stack[--tos];
00498 y = x->left == r ? x->right : x->left;
00499 }
00500 }
00501 else
00502 {
00503
00504
00505
00506
00507 if(x->left == y)
00508 {
00509 newY = y->right;
00510 z = y->left;
00511 }
00512 else
00513 {
00514 newY = y->left;
00515 z = y->right;
00516 }
00517
00518 restructure(t, tos, x, y, z);
00519 y->color = rbTreeBlack;
00520 x->color = rbTreeRed;
00521
00522
00523
00524
00525
00526
00527 stack[tos++] = y;
00528
00529
00530
00531
00532
00533 y = newY;
00534
00535
00536 if(((z = y->left) && z->color == rbTreeRed) ||
00537 ((z = y->right) && z->color == rbTreeRed))
00538 {
00539
00540
00541
00542
00543 b = restructure(t, tos, x, y, z);
00544 b->color = rbTreeRed;
00545 b->left->color = b->right->color = rbTreeBlack;
00546 }
00547 else
00548 {
00549
00550
00551
00552
00553 y->color = rbTreeRed;
00554 x->color = rbTreeBlack;
00555 }
00556
00557 break;
00558 }
00559 }
00560 }
00561 else
00562 {
00563
00564
00565
00566 r->color = rbTreeBlack;
00567 }
00568 }
00569 return returnItem;
00570 }
00571
00572
00573 static int dumpLevel;
00574 static FILE *dumpFile;
00575 static void (*dumpIt)(void *item, FILE *f);
00576
00577 static void rTreeDump(struct rbTreeNode *n)
00578
00579 {
00580 if (n == NULL)
00581 return;
00582 spaceOut(dumpFile, ++dumpLevel * 3);
00583 fprintf(dumpFile, "%c ", (n->color == rbTreeRed ? 'r' : 'b'));
00584 dumpIt(n->item, dumpFile);
00585 fprintf(dumpFile, "\n");
00586 rTreeDump(n->left);
00587 rTreeDump(n->right);
00588 --dumpLevel;
00589 }
00590
00591 void rbTreeDump(struct rbTree *tree, FILE *f,
00592 void (*dumpItem)(void *item, FILE *f))
00593
00594 {
00595 dumpFile = f;
00596 dumpLevel = 0;
00597 dumpIt = dumpItem;
00598 fprintf(f, "rbTreeDump\n");
00599 rTreeDump(tree->root);
00600 }
00601
00602
00603
00604
00605 static void (*doIt)(void *item);
00606 static void *minIt, *maxIt;
00607 static int (*compareIt)(void *, void *);
00608
00609 static void rTreeTraverseRange(struct rbTreeNode *n)
00610
00611 {
00612 if (n != NULL)
00613 {
00614 int minCmp = compareIt(n->item, minIt);
00615 int maxCmp = compareIt(n->item, maxIt);
00616 if (minCmp >= 0)
00617 rTreeTraverseRange(n->left);
00618 if (minCmp >= 0 && maxCmp <= 0)
00619 doIt(n->item);
00620 if (maxCmp <= 0)
00621 rTreeTraverseRange(n->right);
00622 }
00623 }
00624
00625 static void rTreeTraverse(struct rbTreeNode *n)
00626
00627 {
00628 if (n != NULL)
00629 {
00630 rTreeTraverse(n->left);
00631 doIt(n->item);
00632 rTreeTraverse(n->right);
00633 }
00634 }
00635
00636 void rbTreeTraverseRange(struct rbTree *tree, void *minItem, void *maxItem,
00637 void (*doItem)(void *item))
00638
00639
00640 {
00641 doIt = doItem;
00642 minIt = minItem;
00643 maxIt = maxItem;
00644 compareIt = tree->compare;
00645 rTreeTraverseRange(tree->root);
00646 }
00647
00648 void rbTreeTraverse(struct rbTree *tree, void (*doItem)(void *item))
00649
00650 {
00651 doIt = doItem;
00652 compareIt = tree->compare;
00653 rTreeTraverse(tree->root);
00654 }
00655
00656 struct slRef *itList;
00657
00658 static void addRef(void *item)
00659
00660 {
00661 refAdd(&itList, item);
00662 }
00663
00664 struct slRef *rbTreeItemsInRange(struct rbTree *tree, void *minItem, void *maxItem)
00665
00666
00667 {
00668 itList = NULL;
00669 rbTreeTraverseRange(tree, minItem, maxItem, addRef);
00670 slReverse(&itList);
00671 return itList;
00672 }
00673
00674 struct slRef *rbTreeItems(struct rbTree *tree)
00675
00676 {
00677 itList = NULL;
00678 rbTreeTraverse(tree, addRef);
00679 slReverse(&itList);
00680 return itList;
00681 }
00682
00683 int rbTreeCmpString(void *a, void *b)
00684
00685 {
00686 return strcmp(a, b);
00687 }
00688
00689 int rbTreeCmpWord(void *a, void *b)
00690
00691 {
00692 return differentWord(a,b);
00693 }