|
Graphviz 2.29.20120208.0545
|
00001 #include "dthdr.h" 00002 00003 /* Ordered set/multiset 00004 ** dt: dictionary being searched 00005 ** obj: the object to look for. 00006 ** type: search type. 00007 ** 00008 ** Written by Kiem-Phong Vo (5/25/96) 00009 */ 00010 00011 #if __STD_C 00012 static Void_t* dttree(Dt_t* dt, Void_t* obj, int type) 00013 #else 00014 static Void_t* dttree(dt,obj,type) 00015 Dt_t* dt; 00016 Void_t* obj; 00017 int type; 00018 #endif 00019 { 00020 Dtlink_t *root, *t; 00021 int cmp, lk, sz, ky; 00022 Void_t *o, *k, *key; 00023 Dtlink_t *l, *r, *me, link; 00024 int n, minp, turn[DT_MINP]; 00025 Dtcompar_f cmpf; 00026 Dtdisc_t* disc; 00027 00028 UNFLATTEN(dt); 00029 disc = dt->disc; _DTDSC(disc,ky,sz,lk,cmpf); 00030 dt->type &= ~DT_FOUND; 00031 00032 root = dt->data->here; 00033 if(!obj) 00034 { if(!root || !(type&(DT_CLEAR|DT_FIRST|DT_LAST)) ) 00035 return NIL(Void_t*); 00036 00037 if(type&DT_CLEAR) /* delete all objects */ 00038 { if(disc->freef || disc->link < 0) 00039 { do 00040 { while((t = root->left) ) 00041 RROTATE(root,t); 00042 t = root->right; 00043 if(disc->freef) 00044 (*disc->freef)(dt,_DTOBJ(root,lk),disc); 00045 if(disc->link < 0) 00046 (*dt->memoryf)(dt,(Void_t*)root,0,disc); 00047 } while((root = t) ); 00048 } 00049 00050 dt->data->size = 0; 00051 dt->data->here = NIL(Dtlink_t*); 00052 return NIL(Void_t*); 00053 } 00054 else /* computing largest/smallest element */ 00055 { if(type&DT_LAST) 00056 { while((t = root->right) ) 00057 LROTATE(root,t); 00058 } 00059 else /* type&DT_FIRST */ 00060 { while((t = root->left) ) 00061 RROTATE(root,t); 00062 } 00063 00064 dt->data->here = root; 00065 return _DTOBJ(root,lk); 00066 } 00067 } 00068 00069 /* note that link.right is LEFT tree and link.left is RIGHT tree */ 00070 l = r = &link; 00071 00072 /* allow apps to delete an object "actually" in the dictionary */ 00073 if(dt->meth->type == DT_OBAG && (type&(DT_DELETE|DT_DETACH)) ) 00074 { key = _DTKEY(obj,ky,sz); 00075 for(o = dtsearch(dt,obj); o; o = dtnext(dt,o) ) 00076 { k = _DTKEY(o,ky,sz); 00077 if(_DTCMP(dt,key,k,disc,cmpf,sz) != 0) 00078 break; 00079 if(o == obj) 00080 { root = dt->data->here; 00081 l->right = root->left; 00082 r->left = root->right; 00083 goto dt_delete; 00084 } 00085 } 00086 } 00087 00088 if(type&(DT_MATCH|DT_SEARCH|DT_INSERT|DT_ATTACH)) 00089 { key = (type&DT_MATCH) ? obj : _DTKEY(obj,ky,sz); 00090 if(root) 00091 goto do_search; 00092 } 00093 else if(type&DT_RENEW) 00094 { me = (Dtlink_t*)obj; 00095 obj = _DTOBJ(me,lk); 00096 key = _DTKEY(obj,ky,sz); 00097 if(root) 00098 goto do_search; 00099 } 00100 else if(root && _DTOBJ(root,lk) != obj) 00101 { key = _DTKEY(obj,ky,sz); 00102 do_search: 00103 if(dt->meth->type == DT_OSET && 00104 (minp = dt->data->minp) != 0 && (type&(DT_MATCH|DT_SEARCH)) ) 00105 { /* simple search, note that minp should be even */ 00106 for(t = root, n = 0; n < minp; ++n) 00107 { k = _DTOBJ(t,lk); k = _DTKEY(k,ky,sz); 00108 if((cmp = _DTCMP(dt,key,k,disc,cmpf,sz)) == 0) 00109 return _DTOBJ(t,lk); 00110 else 00111 { turn[n] = cmp; 00112 if(!(t = cmp < 0 ? t->left : t->right) ) 00113 return NIL(Void_t*); 00114 } 00115 } 00116 00117 /* exceed search length, top-down splay now */ 00118 for(n = 0; n < minp; n += 2) 00119 { if(turn[n] < 0) 00120 { t = root->left; 00121 if(turn[n+1] < 0) 00122 { rrotate(root,t); 00123 rlink(r,t); 00124 root = t->left; 00125 } 00126 else 00127 { llink(l,t); 00128 rlink(r,root); 00129 root = t->right; 00130 } 00131 } 00132 else 00133 { t = root->right; 00134 if(turn[n+1] > 0) 00135 { lrotate(root,t); 00136 llink(l,t); 00137 root = t->right; 00138 } 00139 else 00140 { rlink(r,t); 00141 llink(l,root); 00142 root = t->left; 00143 } 00144 } 00145 } 00146 } 00147 00148 while(1) 00149 { k = _DTOBJ(root,lk); k = _DTKEY(k,ky,sz); 00150 if((cmp = _DTCMP(dt,key,k,disc,cmpf,sz)) == 0) 00151 break; 00152 else if(cmp < 0) 00153 { if((t = root->left) ) 00154 { k = _DTOBJ(t,lk); k = _DTKEY(k,ky,sz); 00155 if((cmp = _DTCMP(dt,key,k,disc,cmpf,sz)) < 0) 00156 { rrotate(root,t); 00157 rlink(r,t); 00158 if(!(root = t->left) ) 00159 break; 00160 } 00161 else if(cmp == 0) 00162 { rlink(r,root); 00163 root = t; 00164 break; 00165 } 00166 else /* if(cmp > 0) */ 00167 { llink(l,t); 00168 rlink(r,root); 00169 if(!(root = t->right) ) 00170 break; 00171 } 00172 } 00173 else 00174 { rlink(r,root); 00175 root = NIL(Dtlink_t*); 00176 break; 00177 } 00178 } 00179 else /* if(cmp > 0) */ 00180 { if((t = root->right) ) 00181 { k = _DTOBJ(t,lk); k = _DTKEY(k,ky,sz); 00182 if((cmp = _DTCMP(dt,key,k,disc,cmpf,sz)) > 0) 00183 { lrotate(root,t); 00184 llink(l,t); 00185 if(!(root = t->right) ) 00186 break; 00187 } 00188 else if(cmp == 0) 00189 { llink(l,root); 00190 root = t; 00191 break; 00192 } 00193 else /* if(cmp < 0) */ 00194 { rlink(r,t); 00195 llink(l,root); 00196 if(!(root = t->left) ) 00197 break; 00198 } 00199 } 00200 else 00201 { llink(l,root); 00202 root = NIL(Dtlink_t*); 00203 break; 00204 } 00205 } 00206 } 00207 } 00208 00209 if(root) 00210 { /* found it, now isolate it */ 00211 dt->type |= DT_FOUND; 00212 l->right = root->left; 00213 r->left = root->right; 00214 00215 if(type&(DT_SEARCH|DT_MATCH)) 00216 { has_root: 00217 root->left = link.right; 00218 root->right = link.left; 00219 if((dt->meth->type&DT_OBAG) && (type&(DT_SEARCH|DT_MATCH)) ) 00220 { key = _DTOBJ(root,lk); key = _DTKEY(key,ky,sz); 00221 while((t = root->left) ) 00222 { /* find max of left subtree */ 00223 while((r = t->right) ) 00224 LROTATE(t,r); 00225 root->left = t; 00226 00227 /* now see if it's in the same group */ 00228 k = _DTOBJ(t,lk); k = _DTKEY(k,ky,sz); 00229 if(_DTCMP(dt,key,k,disc,cmpf,sz) != 0) 00230 break; 00231 RROTATE(root,t); 00232 } 00233 } 00234 dt->data->here = root; 00235 return _DTOBJ(root,lk); 00236 } 00237 else if(type&DT_NEXT) 00238 { root->left = link.right; 00239 root->right = NIL(Dtlink_t*); 00240 link.right = root; 00241 dt_next: 00242 if((root = link.left) ) 00243 { while((t = root->left) ) 00244 RROTATE(root,t); 00245 link.left = root->right; 00246 goto has_root; 00247 } 00248 else goto no_root; 00249 } 00250 else if(type&DT_PREV) 00251 { root->right = link.left; 00252 root->left = NIL(Dtlink_t*); 00253 link.left = root; 00254 dt_prev: 00255 if((root = link.right) ) 00256 { while((t = root->right) ) 00257 LROTATE(root,t); 00258 link.right = root->left; 00259 goto has_root; 00260 } 00261 else goto no_root; 00262 } 00263 else if(type&(DT_DELETE|DT_DETACH)) 00264 { /* taking an object out of the dictionary */ 00265 dt_delete: 00266 obj = _DTOBJ(root,lk); 00267 if(disc->freef && (type&DT_DELETE)) 00268 (*disc->freef)(dt,obj,disc); 00269 if(disc->link < 0) 00270 (*dt->memoryf)(dt,(Void_t*)root,0,disc); 00271 if((dt->data->size -= 1) < 0) 00272 dt->data->size = -1; 00273 goto no_root; 00274 } 00275 else if(type&(DT_INSERT|DT_ATTACH)) 00276 { if(dt->meth->type&DT_OSET) 00277 goto has_root; 00278 else 00279 { root->left = NIL(Dtlink_t*); 00280 root->right = link.left; 00281 link.left = root; 00282 goto dt_insert; 00283 } 00284 } 00285 else if(type&DT_RENEW) /* a duplicate */ 00286 { if(dt->meth->type&DT_OSET) 00287 { if(disc->freef) 00288 (*disc->freef)(dt,obj,disc); 00289 if(disc->link < 0) 00290 (*dt->memoryf)(dt,(Void_t*)me,0,disc); 00291 } 00292 else 00293 { me->left = NIL(Dtlink_t*); 00294 me->right = link.left; 00295 link.left = me; 00296 dt->data->size += 1; 00297 } 00298 goto has_root; 00299 } 00300 } 00301 else 00302 { /* not found, finish up LEFT and RIGHT trees */ 00303 r->left = NIL(Dtlink_t*); 00304 l->right = NIL(Dtlink_t*); 00305 00306 if(type&DT_NEXT) 00307 goto dt_next; 00308 else if(type&DT_PREV) 00309 goto dt_prev; 00310 else if(type&(DT_SEARCH|DT_MATCH)) 00311 { no_root: 00312 while((t = r->left) ) 00313 r = t; 00314 r->left = link.right; 00315 dt->data->here = link.left; 00316 return (type&DT_DELETE) ? obj : NIL(Void_t*); 00317 } 00318 else if(type&(DT_INSERT|DT_ATTACH)) 00319 { dt_insert: 00320 if(disc->makef && (type&DT_INSERT)) 00321 obj = (*disc->makef)(dt,obj,disc); 00322 if(obj) 00323 { if(lk >= 0) 00324 root = _DTLNK(obj,lk); 00325 else 00326 { root = (Dtlink_t*)(*dt->memoryf) 00327 (dt,NIL(Void_t*),sizeof(Dthold_t),disc); 00328 if(root) 00329 ((Dthold_t*)root)->obj = obj; 00330 else if(disc->makef && disc->freef && 00331 (type&DT_INSERT)) 00332 (*disc->freef)(dt,obj,disc); 00333 } 00334 } 00335 if(root) 00336 { if(dt->data->size >= 0) 00337 dt->data->size += 1; 00338 goto has_root; 00339 } 00340 else goto no_root; 00341 } 00342 else if(type&DT_RENEW) 00343 { root = me; 00344 dt->data->size += 1; 00345 goto has_root; 00346 } 00347 else /*if(type&DT_DELETE)*/ 00348 { obj = NIL(Void_t*); 00349 goto no_root; 00350 } 00351 } 00352 00353 return NIL(Void_t*); 00354 } 00355 00356 /* make this method available */ 00357 static Dtmethod_t _Dtoset = { dttree, DT_OSET }; 00358 static Dtmethod_t _Dtobag = { dttree, DT_OBAG }; 00359 __DEFINE__(Dtmethod_t*,Dtoset,&_Dtoset); 00360 __DEFINE__(Dtmethod_t*,Dtobag,&_Dtobag); 00361 00362 #ifndef KPVDEL /* backward compatibility - delete next time around */ 00363 Dtmethod_t _Dttree = { dttree, DT_OSET }; 00364 __DEFINE__(Dtmethod_t*,Dtorder,&_Dttree); 00365 __DEFINE__(Dtmethod_t*,Dttree,&_Dttree); 00366 #endif 00367 00368 #ifdef NoF 00369 NoF(dttree) 00370 #endif
1.7.4