Annotation of libwww/Library/src/HTBTree.c, revision 2.5

1.1       timbl       1: /*                  Binary Tree for sorting things
                      2: **                  ==============================
                      3: **                      Author: Arthur Secret
                      4: */
                      5: 
                      6: 
                      7: #include "HTUtils.h"
                      8: #include "HTBTree.h"
                      9: #include <stdlib.h>
                     10: #include <string.h>
                     11: 
                     12: #define MAX(a,b) ((a)>(b)?(a):(b))
                     13: 
                     14: 
                     15: 
                     16: 
                     17: 
                     18: PUBLIC HTBTree * HTBTree_new ARGS1(HTComparer, comp)
                     19:     /*********************************************************
                     20:     ** This function returns an HTBTree with memory allocated 
                     21:     ** for it when given a mean to compare things
                     22:     */
                     23: {
                     24:     HTBTree * tree = (HTBTree *)malloc(sizeof(HTBTree));
                     25:     if (tree==NULL) outofmem(__FILE__, "HTBTree_new");
                     26: 
                     27:     tree->compare = comp;
                     28:     tree->top = NULL;
                     29: 
                     30:     return tree;
                     31: }
                     32: 
                     33: 
                     34: 
                     35: 
                     36: 
                     37: PUBLIC void HTBTree_free ARGS1(HTBTree*, tree)
                     38:     /**************************************************************
                     39:     ** This void will free the memory allocated for the whole tree
                     40:     */
                     41: {
                     42:     HTBTElement * wagazou;
                     43: 
                     44:     wagazou = HTBTree_next(tree,NULL);
                     45:     while (wagazou != NULL)
                     46:     {
                     47:         free (wagazou);
                     48:         wagazou = HTBTree_next(tree,wagazou);
                     49:     }
                     50:     free(tree);
                     51: }
                     52: 
                     53: 
                     54: 
                     55: 
                     56: 
                     57: PUBLIC void HTBTree_add ARGS2(
                     58:                    HTBTree*,  tree,
                     59:                    void*,     object)
                     60:     /**********************************************************************
                     61:     ** This void is the core of HTBTree.c . It will
                     62:     **       1/ add a new element to the tree at the right place
                     63:     **          so that the tree remains sorted
                     64:     **       2/ balance the tree to be as fast as possible when reading it
                     65:     */
                     66: {
                     67:     HTBTElement * leopard;
                     68:     HTBTElement * leopard_son;
                     69:     HTBTElement * leopard_father;
                     70:     HTBTElement * leo_brother;
                     71:     BOOL bouboule,bouboule2,first_correction;
                     72:     int depth,depth2;
                     73:         /* leopard is a pointer to the structure that is the father of the new 
                     74:         ** object "object".
                     75:         ** leopard_son is a pointer to the structure that contains or will contain 
                     76:         ** the new object "object".
                     77:         ** leopard_father and leo_brother are pointers that are used to modify the
                     78:         ** depths of upper elements, when needed.
                     79:         **
                     80:         ** bouboule indicates by a value NO when the future father of "object" is 
                     81:         ** found.
                     82:         ** bouboule2 indicates by a value NO when, in case of a difference of depths
                     83:         **  < 2, the top of the tree is encountered and forbids any further try to
                     84:         ** balance the tree.
                     85:         ** first_correction is a boolean used to avoid infinite loops in cases
                     86:         ** such as:
                     87:         **
                     88:         **             3                        3
                     89:         **          4                              4
                     90:         **           5                            5
                     91:         **
                     92:         ** 3 is used here to show that it need not be the top of the tree.
                     93:         */
                     94: 
                     95:     /*
                     96:     ** 1/ Adding of the element to the binary tree
                     97:     */
                     98: 
                     99:     if (tree->top == NULL)
                    100:     {
                    101:         tree->top = (HTBTElement *)malloc(sizeof(HTBTElement));
                    102:         if (tree->top == NULL) outofmem(__FILE__, "HTBTree_add");
                    103:         tree->top->up = NULL;
                    104:         tree->top->object = object;
                    105:         tree->top->left = NULL;
                    106:         tree->top->left_depth = 0;
                    107:         tree->top->right = NULL;
                    108:         tree->top->right_depth = 0;
                    109:     }
                    110:     else
                    111:     {   
                    112:         bouboule = YES;
                    113:         leopard = tree->top;
                    114:         leopard_son = NULL;
                    115:         leopard_father = NULL;
                    116:         leo_brother = NULL;      
                    117:         while (bouboule)
                    118:         {
                    119:             if (tree->compare(object,leopard->object)<0)
                    120:            {
                    121:                 if (leopard->left != NULL) leopard = leopard->left;
                    122:                 else 
                    123:                {
                    124:                     bouboule = NO;
                    125:                     leopard->left = (HTBTElement *)malloc(sizeof(HTBTElement));
                    126:                     if (leopard->left==NULL) outofmem(__FILE__, "HTBTree_add");
                    127:                     leopard_son = leopard->left;
                    128:                     leopard_son->up = leopard;
                    129:                     leopard_son->object = object;
                    130:                     leopard_son->left = NULL;
                    131:                     leopard_son->left_depth = 0;
                    132:                     leopard_son->right = NULL;
                    133:                     leopard_son->right_depth = 0;
                    134:                 }
                    135:            }
                    136:             if (tree->compare(object,leopard->object)>0)
                    137:             {
                    138:                 if (leopard->right != NULL) leopard = leopard->right;
                    139:                 else 
                    140:                 {  
                    141:                     bouboule = NO;
                    142:                     leopard->right = (HTBTElement *)malloc(sizeof(HTBTElement));
                    143:                     if (leopard->right==NULL) outofmem(__FILE__, "HTBTree_add");
                    144:                     leopard_son = leopard->right;
                    145:                     leopard_son->up = leopard;
                    146:                     leopard_son->object = object;
                    147:                     leopard_son->left = NULL;
                    148:                     leopard_son->left_depth = 0;
                    149:                     leopard_son->right = NULL;
                    150:                     leopard_son->right_depth = 0;       
                    151:                }
                    152:             }
                    153:        }
                    154:             /*
                    155:             ** Changing of all depths that need to be changed
                    156:             */
                    157:         leopard_father = leopard;
                    158:         leo_brother = leopard_son;
                    159:         do
                    160:         {
                    161:             if (leopard_father->left == leo_brother)
                    162:             {
                    163:                 depth = leopard_father->left_depth;
                    164:                 leopard_father->left_depth = 1 
                    165:                             + MAX(leo_brother->right_depth,leo_brother->left_depth);
                    166:                 depth2 = leopard_father->left_depth;
                    167:             }
                    168:             else
                    169:            {
                    170:                 depth = leopard_father->right_depth;
                    171:                 leopard_father->right_depth = 1
                    172:                             + MAX(leo_brother->right_depth,leo_brother->left_depth);
                    173:                 depth2 = leopard_father->right_depth;
                    174:             }
                    175:             leo_brother = leopard_father;
                    176:             leopard_father = leopard_father->up;
                    177:         } while ((depth != depth2) && (leopard_father != NULL));
                    178:         
                    179: 
                    180:             /*
                    181:             ** 2/ Balancing the binary tree, if necessary
                    182:             */
                    183:         bouboule2 = YES;
                    184:         first_correction = YES;
                    185:         while ((bouboule2) && (first_correction))
                    186:         {
                    187:             if ((abs(leopard->left_depth - leopard->right_depth)) < 2)
                    188:            {
                    189:                 if (leopard->up != NULL) leopard = leopard->up;
                    190:                 else bouboule2 = NO;
                    191:            }
                    192:             else
                    193:            {                /* We start the process of balancing */
                    194: 
                    195:                 first_correction = NO;
                    196:                     /* 
                    197:                     ** first_correction is a boolean used to avoid infinite 
                    198:                     ** loops in cases such as:
                    199:                     **
                    200:                     **             3                        3
                    201:                     **          4                              4
                    202:                     **           5                            5
                    203:                     **
                    204:                     ** 3 is used to show that it need not be the top of the tree
                    205:                     */
                    206: 
                    207: 
                    208:                 if (leopard->left_depth > leopard->right_depth)
                    209:                {
                    210:                     leopard_son = leopard->left;
                    211:                     leopard->left_depth = leopard_son->right_depth;
                    212:                     leopard_son->right_depth = 1
                    213:                                     + MAX(leopard->right_depth,leopard->left_depth);
                    214:                     if (leopard->up != NULL)
                    215:                    {
                    216:                         leopard_father = leopard->up;
                    217:                         leo_brother = leopard_son;
                    218:                         do 
                    219:                         {
                    220:                             if (leopard_father->left == leo_brother->up)
                    221:                             {
                    222:                                 depth = leopard_father->left_depth;
                    223:                                 leopard_father->left_depth = 1
                    224:                                                     + MAX(leo_brother->left_depth,
                    225:                                                           leo_brother->right_depth);
                    226:                                 depth2 = leopard_father->left_depth;
                    227:                            }
                    228:                             else
                    229:                            {
                    230:                                 depth = leopard_father->right_depth;
                    231:                                 leopard_father->right_depth = 1
                    232:                                                     + MAX(leo_brother->left_depth,
                    233:                                                           leo_brother->right_depth);
                    234:                                 depth2 = leopard_father->right_depth;
                    235:                            }
                    236:                             leo_brother = leopard_father;
                    237:                             leopard_father = leopard_father->up;
                    238:                        } while ((depth != depth2) && (leopard_father != NULL));
                    239:                         leopard_father = leopard->up;
                    240:                         if (leopard_father->left == leopard)
                    241:                        {
                    242:                             /*
                    243:                             **                   3                       3
                    244:                             **               4                       5
                    245:                             ** When tree   5   6        becomes    7    4
                    246:                             **            7 8                          8 6
                    247:                             **
                    248:                             ** 3 is used to show that it may not be the top of the
                    249:                             ** tree.
                    250:                             */ 
                    251:                             leopard_father->left = leopard_son;
                    252:                             leopard->left = leopard_son->right;
                    253:                             leopard_son->right = leopard;
                    254:                         }
                    255:                         if (leopard_father->right == leopard)
                    256:                        {
                    257:                             /*
                    258:                             **          3                       3
                    259:                             **               4                       5
                    260:                             ** When tree   5   6        becomes    7    4
                    261:                             **            7 8                          8 6
                    262:                             **
                    263:                             ** 3 is used to show that it may not be the top of the
                    264:                             ** tree
                    265:                             */
                    266:                             leopard_father->right = leopard_son;
                    267:                             leopard->left = leopard_son->right;
                    268:                             leopard_son->right = leopard;
                    269:                         }
                    270:                         leopard_son->up = leopard_father;
                    271:                    }
                    272:                     else
                    273:                    {
                    274:                         /*
                    275:                         **
                    276:                         **               1                       2
                    277:                         ** When tree   2   3        becomes    4    1
                    278:                         **            4 5                          5 3
                    279:                         **
                    280:                         ** 1 is used to show that it is the top of the tree    
                    281:                         */
                    282:                         leopard_son->up = NULL;
                    283:                         leopard->left = leopard_son->right;
                    284:                         leopard_son->right = leopard;
                    285:                    }
                    286:                     leopard->up = leopard_son;
                    287:                     if (leopard->left != NULL)
                    288:                         leopard->left->up = leopard;
                    289:                }
                    290:                 else
                    291:                {
                    292:                     leopard_son = leopard->right;
                    293:                     leopard->right_depth = leopard_son->left_depth;
                    294:                     leopard_son->left_depth = 1 + 
                    295:                                       MAX(leopard->right_depth,leopard->left_depth);
                    296:                     if (leopard->up != NULL)
                    297:                    {
                    298:                         leopard_father = leopard->up;
                    299:                         leo_brother = leopard_son;
                    300:                         do 
                    301:                         {
                    302:                             if (leopard_father->left == leopard)
                    303:                             {
                    304:                                 depth = leopard_father->left_depth;
                    305:                                 leopard_father->left_depth = 1
                    306:                                                     + MAX(leopard_son->left_depth,
                    307:                                                           leopard_son->right_depth);
                    308:                                 depth2 = leopard_father->left_depth;
                    309:                            }
                    310:                             else
                    311:                            {
                    312:                                 depth = leopard_father->right_depth;
                    313:                                 leopard_father->right_depth = 1
                    314:                                                    + MAX(leopard_son->left_depth,
                    315:                                                          leopard_son->right_depth); 
                    316:                                 depth2 = leopard_father->right_depth;
                    317:                            }
                    318:                             leopard_father = leopard_father->up;
                    319:                             leo_brother = leopard_father;
                    320:                        } while ((depth != depth2) && (leopard_father != NULL));;
                    321:                         leopard_father = leopard->up;
                    322:                         if (leopard_father->left == leopard)
                    323:                        {
                    324:                             /*
                    325:                             **                    3                       3
                    326:                             **               4                       6
                    327:                             ** When tree   5   6        becomes    4    8
                    328:                             **                7 8                 5 7
                    329:                             **
                    330:                             ** 3 is used to show that it may not be the top of the
                    331:                             ** tree.
                    332:                             */
                    333:                             leopard_father->left = leopard_son;
                    334:                             leopard->right = leopard_son->left;
                    335:                             leopard_son->left = leopard;
                    336:                         }
                    337:                         if (leopard_father->right == leopard)
                    338:                        {
                    339:                             /*
                    340:                             **           3                      3
                    341:                             **               4                       6
                    342:                             ** When tree   5   6        becomes    4    8
                    343:                             **                7 8                 5 7
                    344:                             **
                    345:                             ** 3 is used to show that it may not be the top of the
                    346:                             ** tree
                    347:                             */
                    348:                             leopard_father->right = leopard_son;
                    349:                             leopard->right = leopard_son->left;
                    350:                             leopard_son->left = leopard;
                    351:                         }
                    352:                         leopard_son->up = leopard_father;
                    353:                    }
                    354:                     else
                    355:                     {
                    356:                         /*
                    357:                         **
                    358:                         **               1                       3
                    359:                         ** When tree   2   3        becomes    1    5
                    360:                         **                4 5                 2 4
                    361:                         **
                    362:                         ** 1 is used to show that it is the top of the tree.
                    363:                         */
                    364:                         leopard_son->up = NULL;
                    365:                         leopard->right = leopard_son->left;
                    366:                         leopard_son->left = leopard;
                    367:                    }
                    368:                     leopard->up = leopard_son;
                    369:                     leopard->right->up = leopard;
                    370:                }
                    371:            }
                    372:         }
                    373:         while (leopard->up != NULL)
                    374:        {
                    375:             leopard = leopard->up;
                    376:         }
                    377:         tree->top = leopard;
                    378:     }
                    379: }
                    380: 
                    381: 
                    382: 
                    383: PUBLIC HTBTElement * HTBTree_next ARGS2(
                    384:                                HTBTree*,       tree,
                    385:                                HTBTElement*,   ele)
                    386:     /**************************************************************************
                    387:     ** this function returns a pointer to the leftmost element if ele is NULL,
                    388:     ** and to the next object to the right otherways.
                    389:     ** If no elements left, returns a pointer to NULL.
                    390:     */
                    391: {
                    392:     HTBTElement * leopard;
                    393:     HTBTElement * leopard_father;
                    394: 
                    395:     if (ele == NULL)
                    396:     {
                    397:         leopard = tree->top;
                    398:         if (leopard != NULL)
                    399:             while (leopard->left != NULL)
                    400:                 leopard = leopard->left;
                    401:     }
                    402:     else
                    403:     {
                    404:         leopard = ele;
                    405:         if (leopard->right != NULL)
                    406:        {
                    407:             leopard = leopard->right;
                    408:             while (leopard->left != NULL)
                    409:                 leopard = leopard->left;
                    410:        }
                    411:         else
                    412:        {
                    413:             leopard_father = leopard->up;
                    414:             while (leopard_father->right == leopard)
                    415:            {
                    416:                 leopard = leopard_father;
                    417:                 leopard_father = leopard->up;
                    418:            }
                    419:             leopard = leopard_father;
                    420:        }
                    421:     }
                    422:     return leopard;
                    423: }
                    424: 
                    425: 
                    426: #ifdef TEST
                    427: main ()
                    428:     /******************************************************
                    429:     ** This is just a test to show how to handle HTBTree.c
                    430:     */
                    431: {
                    432:     HTBTree * tree;
                    433:     HTBTElement * wagazou;
                    434:     
                    435:     tree = HTBTree_new(strcasecmp);
                    436:     HTBTree_add(tree,"zoo");
                    437:     HTBTree_add(tree,"carot");
                    438:     HTBTree_add(tree,"elephant\t");
                    439:     HTBTree_add(tree,"coat");
                    440:     HTBTree_add(tree,"snake");
                    441:     HTBTree_add(tree,"Peter");
                    442:     HTBTree_add(tree,"Harrison");
                    443:     HTBTree_add(tree,"WWW");
                    444:     wagazou = HTBTree_next(tree,NULL);
                    445:     while (wagazou != NULL)
                    446:     {
                    447:         printf("The next element is %s\n",wagazou->object);
                    448:         wagazou = HTBTree_next(tree,wagazou);
                    449:     }
                    450:     HTBTree_free (tree);
                    451: }
                    452: 
                    453: 
                    454: #endif

Webmaster