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

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