00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "eg_bbtree.h"
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 EGbbtree_t *EGnewBbtree (EGmemPool_t * mem,
00038 EGcompare_f compare)
00039 {
00040 EGbbtree_t *tree = EGmemPoolSMalloc (mem, EGbbtree_t, 1U);
00041 MESSAGE (EG_BBTREE_DEBUGL, "entering");
00042 memset (tree, 0, sizeof (EGbbtree_t));
00043 tree->compare = compare;
00044 tree->mem = mem;
00045 MESSAGE (EG_BBTREE_DEBUGL, "done");
00046 return tree;
00047 }
00048
00049
00050
00051
00052
00053
00054
00055
00056 void EGfreeBbtree (void *tree)
00057 {
00058
00059 EGbbtreeNode_t *c_node;
00060 unsigned int stack_size = 4 * (1.5 + log2l ((long
00061 double) ((EGbbtree_t *) tree)->
00062 size + 1)),
00063 stack_pos = 0;
00064 EGbbtreeNode_t **stack = EGmemPoolSMalloc (((EGbbtree_t *) tree)->mem,
00065 EGbbtreeNode_t *, stack_size);
00066
00067 MESSAGE (EG_BBTREE_DEBUGL, "entering");
00068
00069 stack[stack_pos] = ((EGbbtree_t *) tree)->root;
00070 if (((EGbbtree_t *) tree)->size)
00071 while (~stack_pos)
00072 {
00073 c_node = stack[stack_pos];
00074 stack_pos--;
00075 if (c_node->left)
00076 stack[++stack_pos] = c_node->left;
00077 if (c_node->right)
00078 stack[++stack_pos] = c_node->right;
00079 EGmemPoolSFree (c_node, EGbbtreeNode_t, 1, ((EGbbtree_t *) tree)->mem);
00080 }
00081 ((EGbbtree_t *) tree)->size = 0;
00082
00083
00084 EGmemPoolSFree (stack, EGbbtreeNode_t *, stack_size,
00085 ((EGbbtree_t *) tree)->mem);
00086 EGmemPoolSFree (tree, EGbbtree_t, 1, ((EGbbtree_t *) tree)->mem);
00087 MESSAGE (EG_BBTREE_DEBUGL, "done");
00088 return;
00089 }
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102 int EGbbtreeClear (EGbbtree_t * tree,
00103 EGfree_f dataFree)
00104 {
00105
00106 EGbbtreeNode_t *c_node;
00107 unsigned int stack_size = 4 * (1.5 + log2l ((long double) (tree->size + 1))),
00108 stack_pos = 0;
00109 EGbbtreeNode_t **stack = EGmemPoolSMalloc (tree->mem,
00110 EGbbtreeNode_t *, stack_size);
00111
00112 MESSAGE (EG_BBTREE_DEBUGL, "entering");
00113
00114 stack[stack_pos] = tree->root;
00115 if (tree->size)
00116 while (~stack_pos)
00117 {
00118 c_node = stack[stack_pos];
00119 stack_pos--;
00120 if (c_node->left)
00121 stack[++stack_pos] = c_node->left;
00122 if (c_node->right)
00123 stack[++stack_pos] = c_node->right;
00124 if (dataFree)
00125 dataFree (c_node->this);
00126 EGmemPoolSFree (c_node, EGbbtreeNode_t, 1, tree->mem);
00127 }
00128 tree->size = 0;
00129 tree->root = 0;
00130
00131
00132 EGmemPoolSFree (stack, EGbbtreeNode_t *, stack_size, tree->mem);
00133 MESSAGE (EG_BBTREE_DEBUGL, "done");
00134 return 0;
00135 }
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150 int EGbbtreeClearMP (EGbbtree_t * tree,
00151 EGfreeMP_f dataFree,
00152 EGmemPool_t * datamem)
00153 {
00154
00155 EGbbtreeNode_t *c_node;
00156 unsigned int stack_size = 4 * (1.5 + log2l ((long double) (tree->size + 1))),
00157 stack_pos = 0;
00158 EGbbtreeNode_t **stack = EGmemPoolSMalloc (tree->mem,
00159 EGbbtreeNode_t *, stack_size);
00160
00161 MESSAGE (EG_BBTREE_DEBUGL, "entering");
00162
00163 stack[stack_pos] = tree->root;
00164 if (tree->size)
00165 while (~stack_pos)
00166 {
00167 c_node = stack[stack_pos];
00168 stack_pos--;
00169 if (c_node->left)
00170 stack[++stack_pos] = c_node->left;
00171 if (c_node->right)
00172 stack[++stack_pos] = c_node->right;
00173 if (dataFree)
00174 dataFree (c_node->this, datamem);
00175 EGmemPoolSFree (c_node, EGbbtreeNode_t, 1, tree->mem);
00176 }
00177 tree->size = 0;
00178 tree->root = 0;
00179
00180
00181 EGmemPoolSFree (stack, EGbbtreeNode_t *, stack_size, tree->mem);
00182 MESSAGE (EG_BBTREE_DEBUGL, "done");
00183 return 0;
00184 }
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196 EGbbtreeNode_t *EGbbtreeFind (EGbbtree_t * tree,
00197 const void *elem)
00198 {
00199
00200 EGbbtreeNode_t *c_node = tree->root;
00201 int rval = 0;
00202
00203 MESSAGE (EG_BBTREE_DEBUGL, "entering");
00204
00205 while (c_node)
00206 {
00207 rval = tree->compare (elem, c_node->this);
00208 if (!rval)
00209 break;
00210 if (rval < 0)
00211 c_node = c_node->left;
00212 else
00213 c_node = c_node->right;
00214 }
00215
00216
00217 MESSAGE (EG_BBTREE_DEBUGL, "done");
00218 return c_node;
00219 }
00220
00221
00222
00223 #define EGbbtreeLeftDepth(__node) ((__node)->left?(__node)->left->depth:0U)
00224
00225
00226
00227 #define EGbbtreeRightDepth(__node) ((__node)->right?(__node)->right->depth:0U)
00228
00229
00230
00231
00232 static inline int EGbbtreeUpdateDepth (EGbbtreeNode_t * const p_node)
00233 {
00234 p_node->depth = EGbbtreeLeftDepth (p_node);
00235 if (p_node->right && p_node->depth < p_node->right->depth)
00236 p_node->depth = p_node->right->depth;
00237 p_node->depth++;
00238 return 0;
00239 }
00240
00241
00242
00243
00244
00245
00246
00247
00248 static inline int EGbbtreeRotateRight (EGbbtree_t * tree,
00249 EGbbtreeNode_t ** p_node)
00250 {
00251
00252 EGbbtreeNode_t *c_node = (*p_node)->left;
00253 MESSAGE (EG_BBTREE_DEBUGL, "entering at node %p", (void *) (*p_node));
00254
00255
00256 if (!(c_node->parent = (*p_node)->parent))
00257 tree->root = c_node;
00258 else
00259 {
00260 if ((*p_node)->parent->left == (*p_node))
00261 (*p_node)->parent->left = c_node;
00262 else
00263 (*p_node)->parent->right = c_node;
00264 }
00265 if (((*p_node)->left = c_node->right))
00266 (*p_node)->left->parent = (*p_node);
00267 c_node->right = (*p_node);
00268 (*p_node)->parent = c_node;
00269
00270 EGbbtreeUpdateDepth (*p_node);
00271
00272 (*p_node) = c_node;
00273
00274 EGbbtreeUpdateDepth (*p_node);
00275 MESSAGE (EG_BBTREE_DEBUGL, "done");
00276 return 0;
00277 }
00278
00279
00280
00281
00282
00283
00284
00285
00286 static inline int EGbbtreeRotateLeft (EGbbtree_t * tree,
00287 EGbbtreeNode_t ** p_node)
00288 {
00289
00290 EGbbtreeNode_t *c_node = (*p_node)->right;
00291 MESSAGE (EG_BBTREE_DEBUGL, "entering at node %p", (void *) (*p_node));
00292
00293
00294 if (!(c_node->parent = (*p_node)->parent))
00295 tree->root = c_node;
00296 else
00297 {
00298 if ((*p_node)->parent->left == (*p_node))
00299 (*p_node)->parent->left = c_node;
00300 else
00301 (*p_node)->parent->right = c_node;
00302 }
00303 if (((*p_node)->right = c_node->left))
00304 (*p_node)->right->parent = (*p_node);
00305 c_node->left = (*p_node);
00306 (*p_node)->parent = c_node;
00307
00308 EGbbtreeUpdateDepth (*p_node);
00309
00310 (*p_node) = c_node;
00311
00312 EGbbtreeUpdateDepth (*p_node);
00313 MESSAGE (EG_BBTREE_DEBUGL, "done");
00314 return 0;
00315 }
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325 static inline int EGbbtreeBalance (EGbbtree_t * tree,
00326 EGbbtreeNode_t ** p_node)
00327 {
00328
00329 unsigned diff;
00330 int rval = 0;
00331 MESSAGE (EG_BBTREE_DEBUGL, "entering");
00332
00333
00334 while (*p_node)
00335 {
00336
00337 EGbbtreeUpdateDepth (*p_node);
00338 diff = EGbbtreeLeftDepth (*p_node) - EGbbtreeRightDepth (*p_node);
00339
00340 switch (diff)
00341 {
00342
00343 case 2U:
00344 if (EGbbtreeRightDepth ((*p_node)->left) >
00345 EGbbtreeLeftDepth ((*p_node)->left))
00346 {
00347 (*p_node) = (*p_node)->left;
00348 rval = EGbbtreeRotateLeft (tree, p_node);
00349 CHECKRVAL (rval);
00350 (*p_node) = (*p_node)->parent;
00351 }
00352 rval = EGbbtreeRotateRight (tree, p_node);
00353 CHECKRVAL (rval);
00354 break;
00355
00356 case (-2U):
00357 if (EGbbtreeLeftDepth ((*p_node)->right) >
00358 EGbbtreeRightDepth ((*p_node)->right))
00359 {
00360 (*p_node) = (*p_node)->right;
00361 rval = EGbbtreeRotateRight (tree, p_node);
00362 CHECKRVAL (rval);
00363 (*p_node) = (*p_node)->parent;
00364 }
00365 rval = EGbbtreeRotateLeft (tree, p_node);
00366 CHECKRVAL (rval);
00367 break;
00368
00369 case 1U:
00370 case 0U:
00371 case (-1U):
00372 break;
00373
00374 default:
00375 rval = 1;
00376 TESTG (1, CLEANUP, "unknown depth difference %u, fix the code!", diff);
00377 break;
00378
00379 }
00380 MESSAGE (EG_BBTREE_DEBUGL, " setting pnode(%p) to parent (%p)",
00381 (void *) (*p_node), (void *) ((*p_node)->parent));
00382 (*p_node) = (*p_node)->parent;
00383 }
00384 CLEANUP:
00385 MESSAGE (EG_BBTREE_DEBUGL, "done");
00386 return rval;
00387 }
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401 EGbbtreeNode_t *EGbbtreeAdd (EGbbtree_t * tree,
00402 void *elem)
00403 {
00404
00405 EGbbtreeNode_t *c_node = tree->root,
00406 *p_node = 0;
00407 int rval = 0;
00408 MESSAGE (EG_BBTREE_DEBUGL, "entering");
00409
00410
00411 while (c_node)
00412 {
00413 rval = tree->compare (elem, c_node->this);
00414 p_node = c_node;
00415 c_node = (rval < 0) ? c_node->left : ((rval > 0) ? c_node->right : 0);
00416 }
00417
00418
00419
00420 if (p_node)
00421 {
00422 if (rval < 0)
00423 p_node->left = c_node = EGmemPoolSMalloc (tree->mem, EGbbtreeNode_t, 1U);
00424 else
00425 p_node->right = c_node = EGmemPoolSMalloc (tree->mem, EGbbtreeNode_t, 1U);
00426 }
00427 else
00428 {
00429 tree->root = c_node = EGmemPoolSMalloc (tree->mem, EGbbtreeNode_t, 1U);
00430 }
00431 memset (c_node, 0, sizeof (EGbbtreeNode_t));
00432 c_node->this = elem;
00433 c_node->parent = p_node;
00434 c_node->depth = 1;
00435 tree->size++;
00436
00437
00438 rval = EGbbtreeBalance (tree, &p_node);
00439 ADVCHECKRVAL (rval, 0);
00440
00441
00442 MESSAGE (EG_BBTREE_DEBUGL, "done");
00443 return c_node;
00444 }
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455 EGbbtreeNode_t *EGbbtreePredecessor (EGbbtreeNode_t * node)
00456 {
00457
00458 EGbbtreeNode_t *c_node = node->left,
00459 *x_node = node;
00460 MESSAGE (EG_BBTREE_DEBUGL, "entering");
00461 if (c_node)
00462 {
00463 while (c_node->right)
00464 c_node = c_node->right;
00465 MESSAGE (EG_BBTREE_DEBUGL, "done");
00466 return c_node;
00467 }
00468 c_node = node->parent;
00469 while (c_node && x_node == c_node->left)
00470 {
00471 x_node = c_node;
00472 c_node = c_node->parent;
00473 }
00474 MESSAGE (EG_BBTREE_DEBUGL, "done");
00475 return c_node;
00476 }
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487 EGbbtreeNode_t *EGbbtreeSuccessor (EGbbtreeNode_t * node)
00488 {
00489
00490 EGbbtreeNode_t *c_node = node->right,
00491 *x_node = node;
00492 MESSAGE (EG_BBTREE_DEBUGL, "entering");
00493 if (c_node)
00494 {
00495 while (c_node->left)
00496 c_node = c_node->left;
00497 MESSAGE (EG_BBTREE_DEBUGL, "done");
00498 return c_node;
00499 }
00500 c_node = node->parent;
00501 while (c_node && x_node == c_node->right)
00502 {
00503 x_node = c_node;
00504 c_node = c_node->parent;
00505 }
00506 MESSAGE (EG_BBTREE_DEBUGL, "done");
00507 return c_node;
00508 }
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524 int EGbbtreeRemove (EGbbtree_t * tree,
00525 EGbbtreeNode_t * node)
00526 {
00527
00528 EGbbtreeNode_t *p_node = node->parent;
00529 EGbbtreeNode_t *n_node;
00530 MESSAGE (EG_BBTREE_DEBUGL, "entering");
00531
00532
00533
00534
00535 if (node->left && node->right)
00536 {
00537 n_node = EGbbtreePredecessor (node);
00538
00539
00540
00541 if (n_node->parent == node)
00542 {
00543 if ((n_node->parent = node->parent))
00544 {
00545 if (node->parent->left == node)
00546 node->parent->left = n_node;
00547 else
00548 node->parent->right = n_node;
00549 }
00550 else
00551 tree->root = n_node;
00552
00553 n_node->right = node->right;
00554 n_node->right->parent = n_node;
00555 p_node = n_node;
00556 EGbbtreeUpdateDepth (n_node);
00557 goto END;
00558 }
00559
00560 p_node = n_node->parent;
00561 if ((n_node->parent = node->parent))
00562 {
00563 if (node->parent->left == node)
00564 node->parent->left = n_node;
00565 else
00566 node->parent->right = n_node;
00567 }
00568 else
00569 tree->root = n_node;
00570
00571 EXIT (node == p_node, "node and p_node are equal");
00572 node->parent = p_node;
00573 if (node->parent->left == n_node)
00574 node->parent->left = node;
00575 else
00576 node->parent->right = node;
00577
00578 n_node->right = node->left;
00579 if ((node->left = n_node->left))
00580 node->left->parent = node;
00581
00582 if ((n_node->left = n_node->right))
00583 n_node->left->parent = n_node;
00584
00585 if ((n_node->right = node->right))
00586 node->right->parent = n_node;
00587
00588 node->right = 0;
00589
00590 EGbbtreeUpdateDepth (n_node);
00591 EGbbtreeUpdateDepth (node);
00592 }
00593
00594
00595 if (node->right)
00596 {
00597 if (p_node)
00598 {
00599 if (p_node->left == node)
00600 p_node->left = node->right;
00601 else
00602 p_node->right = node->right;
00603 node->right->parent = p_node;
00604 }
00605 else
00606 {
00607 tree->root = node->right;
00608 node->right->parent = 0;
00609 }
00610 }
00611 else if (node->left)
00612 {
00613 if (p_node)
00614 {
00615 if (p_node->left == node)
00616 p_node->left = node->left;
00617 else
00618 p_node->right = node->left;
00619 node->left->parent = p_node;
00620 }
00621 else
00622 {
00623 tree->root = node->left;
00624 node->left->parent = 0;
00625 }
00626 }
00627
00628
00629 else
00630 {
00631 if (p_node)
00632 {
00633 if (p_node->left == node)
00634 p_node->left = 0;
00635 else
00636 p_node->right = 0;
00637 }
00638 else
00639 tree->root = 0;
00640 }
00641 END:
00642
00643 EGmemPoolSFree (node, EGbbtreeNode_t, 1, tree->mem);
00644 tree->size--;
00645
00646 MESSAGE (EG_BBTREE_DEBUGL, "done");
00647 return EGbbtreeBalance (tree, &p_node);
00648 }
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659 void EGbbtreeDisplay (EGbbtree_t * tree,
00660 EGdisplay_f dataDisplay,
00661 FILE * file)
00662 {
00663
00664 EGbbtreeNode_t *c_node;
00665 unsigned int stack_size = 4 * (1.5 + log2l ((long double) (tree->size + 1))),
00666 stack_pos = 0;
00667 EGbbtreeNode_t **stack = EGmemPoolSMalloc (tree->mem,
00668 EGbbtreeNode_t *, stack_size);
00669 MESSAGE (EG_BBTREE_DEBUGL, "entering");
00670
00671
00672 stack[stack_pos] = tree->root;
00673
00674
00675 fprintf (file, "\nTree %p:\n"
00676 "\tNodes : %u\n"
00677 "\tPool : %p\n"
00678 "\tCompare: %tX\n", (void *) tree, tree->size,
00679 (void *) tree->mem, (size_t) (tree->compare));
00680
00681 if (tree->size)
00682 while (~stack_pos)
00683 {
00684 c_node = stack[stack_pos];
00685 stack_pos--;
00686 if (c_node->left)
00687 stack[++stack_pos] = c_node->left;
00688 if (c_node->right)
00689 stack[++stack_pos] = c_node->right;
00690 fprintf (file, " Node %p (DP:%d,THS:%p)\n", (void *) c_node,
00691 c_node->depth, c_node->this);
00692 if (dataDisplay)
00693 dataDisplay (c_node->this, file);
00694 }
00695
00696
00697 EGmemPoolSFree (stack, EGbbtreeNode_t *, stack_size,
00698 ((EGbbtree_t *) tree)->mem);
00699 MESSAGE (EG_BBTREE_DEBUGL, "done");
00700 return;
00701 }
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711 EGbbtreeNode_t *EGbbtreeMin (EGbbtree_t * tree)
00712 {
00713 EGbbtreeNode_t *root = tree->root;
00714 MESSAGE (EG_BBTREE_DEBUGL, "entering");
00715 while (root && root->left)
00716 root = root->left;
00717 MESSAGE (EG_BBTREE_DEBUGL, "done");
00718 return root;
00719 }
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729 EGbbtreeNode_t *EGbbtreeMax (EGbbtree_t * tree)
00730 {
00731 EGbbtreeNode_t *root = tree->root;
00732 MESSAGE (EG_BBTREE_DEBUGL, "entering");
00733 while (root && root->right)
00734 root = root->right;
00735 MESSAGE (EG_BBTREE_DEBUGL, "done");
00736 return root;
00737 }
00738
00739
00740
00741
00742
00743