/misc/src/release/graphviz-2.18-1/src/graphviz-2.18/lib/cdt/dttree.c

Go to the documentation of this file.
00001 /* $Id: dttree.c,v 1.1.1.1 2004/12/23 04:04:01 ellson Exp $ $Revision: 1.1.1.1 $ */
00002 /* vim:set shiftwidth=4 ts=8: */
00003 
00004 /**********************************************************
00005 *      This software is part of the graphviz package      *
00006 *                http://www.graphviz.org/                 *
00007 *                                                         *
00008 *            Copyright (c) 1994-2004 AT&T Corp.           *
00009 *                and is licensed under the                *
00010 *            Common Public License, Version 1.0           *
00011 *                      by AT&T Corp.                      *
00012 *                                                         *
00013 *        Information and Software Systems Research        *
00014 *              AT&T Research, Florham Park NJ             *
00015 **********************************************************/
00016 
00017 #include        "dthdr.h"
00018 
00019 #ifdef DMALLOC
00020 #include "dmalloc.h"
00021 #endif
00022 
00023 /*      Ordered set/multiset
00024 **      dt:     dictionary being searched
00025 **      obj:    the object to look for.
00026 **      type:   search type.
00027 **
00028 **      Written by Kiem-Phong Vo (5/25/96)
00029 */
00030 
00031 #if __STD_C
00032 static Void_t *dttree(Dt_t * dt, Void_t * obj, int type)
00033 #else
00034 static Void_t *dttree(dt, obj, type)
00035 Dt_t *dt;
00036 Void_t *obj;
00037 int type;
00038 #endif
00039 {
00040     reg Dtlink_t *root, *t;
00041     reg int cmp, lk, sz, ky;
00042     reg Void_t *k, *key;
00043     reg Dtcompar_f cmpf;
00044     reg Dtdisc_t *disc;
00045     reg Dtlink_t *l, *r, *me;
00046     Dtlink_t link;
00047 
00048     me = 0;
00049     UNFLATTEN(dt);
00050     INITDISC(dt, disc, ky, sz, lk, cmpf);
00051 
00052     root = dt->data->here;
00053     if (!obj) {
00054         if (!root || !(type & (DT_CLEAR | DT_FIRST | DT_LAST)))
00055             return NIL(Void_t *);
00056 
00057         if (type & DT_CLEAR) {  /* delete all objects */
00058             if (disc->freef || disc->link < 0) {
00059                 do {
00060                     while ((t = root->left))
00061                         RROTATE(root, t);
00062                     t = root->right;
00063                     if (disc->freef)
00064                         (*disc->freef) (dt, OBJ(root, lk), disc);
00065                     if (disc->link < 0)
00066                         (*dt->memoryf) (dt, (Void_t *) root, 0, disc);
00067                 } while ((root = t));
00068             }
00069 
00070             dt->data->size = 0;
00071             dt->data->here = NIL(Dtlink_t *);
00072             return NIL(Void_t *);
00073         } else {                /* computing largest/smallest element */
00074             if (type & DT_LAST) {
00075                 while ((t = root->right))
00076                     LROTATE(root, t);
00077             } else {            /* type&DT_FIRST */
00078                 while ((t = root->left))
00079                     RROTATE(root, t);
00080             }
00081 
00082             dt->data->here = root;
00083             return OBJ(root, lk);
00084         }
00085     }
00086 
00087     /* note that link.right is LEFT tree and link.left is RIGHT tree */
00088     l = r = &link;
00089 
00090     if (type & (DT_MATCH | DT_SEARCH | DT_INSERT | DT_ATTACH)) {
00091         key = (type & DT_MATCH) ? obj : KEY(obj, ky, sz);
00092         if (root)
00093             goto do_search;
00094     } else if (type & DT_RENEW) {
00095         me = (Dtlink_t *) obj;
00096         obj = OBJ(me, lk);
00097         key = KEY(obj, ky, sz);
00098         if (root)
00099             goto do_search;
00100     } else if (root && OBJ(root, lk) != obj) {
00101         key = KEY(obj, ky, sz);
00102       do_search:
00103         while (1) {
00104             k = OBJ(root, lk);
00105             k = KEY(k, ky, sz);
00106             if ((cmp = CMP(dt, key, k, disc, cmpf, sz)) == 0)
00107                 break;
00108             else if (cmp < 0) {
00109                 if ((t = root->left)) {
00110                     k = OBJ(t, lk);
00111                     k = KEY(k, ky, sz);
00112                     if ((cmp = CMP(dt, key, k, disc, cmpf, sz)) < 0) {
00113                         RROTATE(root, t);
00114                         RLINK(r, root);
00115                         if (!(root = root->left))
00116                             break;
00117                     } else if (cmp == 0) {
00118                         RROTATE(root, t);
00119                         break;
00120                     } else {    /* if(cmp > 0) */
00121                         LLINK(l, t);
00122                         RLINK(r, root);
00123                         if (!(root = t->right))
00124                             break;
00125                     }
00126                 } else {
00127                     RLINK(r, root);
00128                     root = NIL(Dtlink_t *);
00129                     break;
00130                 }
00131             } else {            /* if(cmp > 0) */
00132                 if ((t = root->right)) {
00133                     k = OBJ(t, lk);
00134                     k = KEY(k, ky, sz);
00135                     if ((cmp = CMP(dt, key, k, disc, cmpf, sz)) > 0) {
00136                         LROTATE(root, t);
00137                         LLINK(l, root);
00138                         if (!(root = root->right))
00139                             break;
00140                     } else if (cmp == 0) {
00141                         LROTATE(root, t);
00142                         break;
00143                     } else {    /* if(cmp < 0) */
00144                         RLINK(r, t);
00145                         LLINK(l, root);
00146                         if (!(root = t->left))
00147                             break;
00148                     }
00149                 } else {
00150                     LLINK(l, root);
00151                     root = NIL(Dtlink_t *);
00152                     break;
00153                 }
00154             }
00155         }
00156     }
00157 
00158     if (root) {                 /* found it, now isolate it */
00159         l->right = root->left;
00160         r->left = root->right;
00161 
00162         if (type & (DT_SEARCH | DT_MATCH)) {
00163           has_root:
00164             root->left = link.right;
00165             root->right = link.left;
00166             if ((dt->meth->type & DT_OBAG)
00167                 && (type & (DT_SEARCH | DT_MATCH))) {
00168                 key = OBJ(root, lk);
00169                 key = KEY(key, ky, sz);
00170                 while ((t = root->left)) {
00171                     k = OBJ(t, lk);
00172                     k = KEY(k, ky, sz);
00173                     if (CMP(dt, key, k, disc, cmpf, sz) != 0)
00174                         break;
00175                     RROTATE(root, t);
00176                 }
00177             }
00178             dt->data->here = root;
00179             return OBJ(root, lk);
00180         } else if (type & DT_NEXT) {
00181             root->left = link.right;
00182             root->right = NIL(Dtlink_t *);
00183             link.right = root;
00184           dt_next:
00185             if ((root = link.left)) {
00186                 while ((t = root->left))
00187                     RROTATE(root, t);
00188                 link.left = root->right;
00189                 goto has_root;
00190             } else
00191                 goto no_root;
00192         } else if (type & DT_PREV) {
00193             root->right = link.left;
00194             root->left = NIL(Dtlink_t *);
00195             link.left = root;
00196           dt_prev:
00197             if ((root = link.right)) {
00198                 while ((t = root->right))
00199                     LROTATE(root, t);
00200                 link.right = root->left;
00201                 goto has_root;
00202             } else
00203                 goto no_root;
00204         } else if (type & (DT_DELETE | DT_DETACH)) {
00205             obj = OBJ(root, lk);
00206             if (disc->freef && (type & DT_DELETE))
00207                 (*disc->freef) (dt, obj, disc);
00208             if (disc->link < 0)
00209                 (*dt->memoryf) (dt, (Void_t *) root, 0, disc);
00210             if ((dt->data->size -= 1) < 0)
00211                 dt->data->size = -1;
00212             goto no_root;
00213         } else if (type & (DT_INSERT | DT_ATTACH)) {
00214             if (dt->meth->type & DT_OSET)
00215                 goto has_root;
00216             else {
00217                 root->left = NIL(Dtlink_t *);
00218                 root->right = link.left;
00219                 link.left = root;
00220                 goto dt_insert;
00221             }
00222         } else if (type & DT_RENEW) {   /* a duplicate */
00223             if (dt->meth->type & DT_OSET) {
00224                 if (disc->freef)
00225                     (*disc->freef) (dt, obj, disc);
00226                 if (disc->link < 0)
00227                     (*dt->memoryf) (dt, (Void_t *) me, 0, disc);
00228             } else {
00229                 me->left = NIL(Dtlink_t *);
00230                 me->right = link.left;
00231                 link.left = me;
00232                 dt->data->size += 1;
00233             }
00234             goto has_root;
00235         }
00236     } else {                    /* not found, finish up LEFT and RIGHT trees */
00237         r->left = NIL(Dtlink_t *);
00238         l->right = NIL(Dtlink_t *);
00239 
00240         if (type & (DT_SEARCH | DT_MATCH)) {
00241           no_root:
00242             while ((t = r->left))
00243                 r = t;
00244             r->left = link.right;
00245             dt->data->here = link.left;
00246             return (type & DT_DELETE) ? obj : NIL(Void_t *);
00247         } else if (type & (DT_INSERT | DT_ATTACH)) {
00248           dt_insert:
00249             if (disc->makef && (type & DT_INSERT))
00250                 obj = (*disc->makef) (dt, obj, disc);
00251             if (obj) {
00252                 if (lk >= 0)
00253                     root = ELT(obj, lk);
00254                 else {
00255                     root = (Dtlink_t *) (*dt->memoryf)
00256                         (dt, NIL(Void_t *), sizeof(Dthold_t), disc);
00257                     if (root)
00258                         ((Dthold_t *) root)->obj = obj;
00259                     else if (disc->makef && disc->freef &&
00260                              (type & DT_INSERT))
00261                         (*disc->freef) (dt, obj, disc);
00262                 }
00263             }
00264             if (root) {
00265                 if (dt->data->size >= 0)
00266                     dt->data->size += 1;
00267                 goto has_root;
00268             } else
00269                 goto no_root;
00270         } else if (type & DT_NEXT)
00271             goto dt_next;
00272         else if (type & DT_PREV)
00273             goto dt_prev;
00274         else if (type & DT_RENEW) {
00275             root = me;
00276             dt->data->size += 1;
00277             goto has_root;
00278         } else {                /*if(type&DT_DELETE) */
00279             obj = NIL(Void_t *);
00280             goto no_root;
00281         }
00282     }
00283 
00284     return NIL(Void_t *);
00285 }
00286 
00287 /* make this method available */
00288 static Dtmethod_t _Dtoset = { dttree, DT_OSET };
00289 static Dtmethod_t _Dtobag = { dttree, DT_OBAG };
00290 
00291 __DEFINE__(Dtmethod_t *, Dtoset, &_Dtoset);
00292 __DEFINE__(Dtmethod_t *, Dtobag, &_Dtobag);
00293 
00294 #ifndef KPVDEL                  /* backward compatibility - delete next time around */
00295 Dtmethod_t _Dttree = { dttree, DT_OSET };
00296 
00297 __DEFINE__(Dtmethod_t *, Dtorder, &_Dttree);
00298 __DEFINE__(Dtmethod_t *, Dttree, &_Dttree);
00299 #endif

Generated on Mon Mar 31 19:03:23 2008 for Graphviz by  doxygen 1.5.1