Graphviz 12.0.1~dev.20240715.2254
Loading...
Searching...
No Matches
dttree.c
Go to the documentation of this file.
1#include <cdt/dthdr.h>
2#include <stdlib.h>
3
4/* Ordered set/multiset
5** dt: dictionary being searched
6** obj: the object to look for.
7** type: search type.
8**
9** Written by Kiem-Phong Vo (5/25/96)
10*/
11
12static void* dttree(Dt_t* dt, void* obj, int type)
13{
14 Dtlink_t *root, *t;
15 int cmp, lk, sz, ky;
16 void *o, *k, *key;
17 Dtlink_t *l, *r, *me = NULL, link;
19 Dtdisc_t* disc;
20
21 UNFLATTEN(dt);
22 disc = dt->disc; _DTDSC(disc,ky,sz,lk,cmpf);
23
24 root = dt->data->here;
25 if(!obj)
26 { if(!root || !(type&(DT_CLEAR|DT_FIRST|DT_LAST)) )
27 return NULL;
28
29 if(type&DT_CLEAR) /* delete all objects */
30 { if(disc->freef || disc->link < 0)
31 { do
32 { while((t = root->left) )
33 RROTATE(root,t);
34 t = root->right;
35 if(disc->freef)
36 disc->freef(_DTOBJ(root, lk));
37 if(disc->link < 0)
38 free(root);
39 } while((root = t) );
40 }
41
42 dt->data->size = 0;
43 dt->data->here = NULL;
44 return NULL;
45 }
46 else /* computing largest/smallest element */
47 { if(type&DT_LAST)
48 { while((t = root->right) )
49 LROTATE(root,t);
50 }
51 else /* type&DT_FIRST */
52 { while((t = root->left) )
53 RROTATE(root,t);
54 }
55
56 dt->data->here = root;
57 return _DTOBJ(root,lk);
58 }
59 }
60
61 /* note that link.right is LEFT tree and link.left is RIGHT tree */
62 l = r = &link;
63
64 /* allow apps to delete an object "actually" in the dictionary */
65 if(dt->meth->type == DT_OBAG && (type&(DT_DELETE|DT_DETACH)) )
66 { key = _DTKEY(obj,ky,sz);
67 for(o = dtsearch(dt,obj); o; o = dtnext(dt,o) )
68 { k = _DTKEY(o,ky,sz);
69 if(_DTCMP(key, k, cmpf, sz) != 0)
70 break;
71 if(o == obj)
72 { root = dt->data->here;
73 l->right = root->left;
74 r->left = root->right;
75 goto dt_delete;
76 }
77 }
78 }
79
81 { key = (type&DT_MATCH) ? obj : _DTKEY(obj,ky,sz);
82 if(root)
83 goto do_search;
84 }
85 else if(type&DT_RENEW)
86 { me = obj;
87 obj = _DTOBJ(me,lk);
88 key = _DTKEY(obj,ky,sz);
89 if(root)
90 goto do_search;
91 }
92 else if(root && _DTOBJ(root,lk) != obj)
93 { key = _DTKEY(obj,ky,sz);
94 do_search:
95 while(1)
96 { k = _DTOBJ(root,lk); k = _DTKEY(k,ky,sz);
97 if((cmp = _DTCMP(key, k, cmpf, sz)) == 0)
98 break;
99 else if(cmp < 0)
100 { if((t = root->left) )
101 { k = _DTOBJ(t,lk); k = _DTKEY(k,ky,sz);
102 if((cmp = _DTCMP(key, k, cmpf, sz)) < 0)
103 { rrotate(root,t);
104 rlink(r,t);
105 if(!(root = t->left) )
106 break;
107 }
108 else if(cmp == 0)
109 { rlink(r,root);
110 root = t;
111 break;
112 }
113 else /* if(cmp > 0) */
114 { llink(l,t);
115 rlink(r,root);
116 if(!(root = t->right) )
117 break;
118 }
119 }
120 else
121 { rlink(r,root);
122 root = NULL;
123 break;
124 }
125 }
126 else /* if(cmp > 0) */
127 { if((t = root->right) )
128 { k = _DTOBJ(t,lk); k = _DTKEY(k,ky,sz);
129 if((cmp = _DTCMP(key, k, cmpf, sz)) > 0)
130 { lrotate(root,t);
131 llink(l,t);
132 if(!(root = t->right) )
133 break;
134 }
135 else if(cmp == 0)
136 { llink(l,root);
137 root = t;
138 break;
139 }
140 else /* if(cmp < 0) */
141 { rlink(r,t);
142 llink(l,root);
143 if(!(root = t->left) )
144 break;
145 }
146 }
147 else
148 { llink(l,root);
149 root = NULL;
150 break;
151 }
152 }
153 }
154 }
155
156 if(root)
157 { /* found it, now isolate it */
158 l->right = root->left;
159 r->left = root->right;
160
162 { has_root:
163 root->left = link.right;
164 root->right = link.left;
165 if((dt->meth->type&DT_OBAG) && (type&(DT_SEARCH|DT_MATCH)) )
166 { key = _DTOBJ(root,lk); key = _DTKEY(key,ky,sz);
167 while((t = root->left) )
168 { /* find max of left subtree */
169 while((r = t->right) )
170 LROTATE(t,r);
171 root->left = t;
172
173 /* now see if it's in the same group */
174 k = _DTOBJ(t,lk); k = _DTKEY(k,ky,sz);
175 if(_DTCMP(key, k, cmpf, sz) != 0)
176 break;
177 RROTATE(root,t);
178 }
179 }
180 dt->data->here = root;
181 return _DTOBJ(root,lk);
182 }
183 else if(type&DT_NEXT)
184 { root->left = link.right;
185 root->right = NULL;
186 link.right = root;
187 dt_next:
188 if((root = link.left) )
189 { while((t = root->left) )
190 RROTATE(root,t);
191 link.left = root->right;
192 goto has_root;
193 }
194 else goto no_root;
195 }
196 else if(type&DT_PREV)
197 { root->right = link.left;
198 root->left = NULL;
199 link.left = root;
200 dt_prev:
201 if((root = link.right) )
202 { while((t = root->right) )
203 LROTATE(root,t);
204 link.right = root->left;
205 goto has_root;
206 }
207 else goto no_root;
208 }
209 else if(type&(DT_DELETE|DT_DETACH))
210 { /* taking an object out of the dictionary */
211 dt_delete:
212 obj = _DTOBJ(root,lk);
213 if(disc->freef && (type&DT_DELETE))
214 disc->freef(obj);
215 if(disc->link < 0)
216 free(root);
217 if((dt->data->size -= 1) < 0)
218 dt->data->size = -1;
219 goto no_root;
220 }
221 else if(type&DT_INSERT)
222 { if(dt->meth->type&DT_OSET)
223 goto has_root;
224 else
225 { root->left = NULL;
226 root->right = link.left;
227 link.left = root;
228 goto dt_insert;
229 }
230 }
231 else if(type&DT_RENEW) /* a duplicate */
232 { if(dt->meth->type&DT_OSET)
233 { if(disc->freef)
234 disc->freef(obj);
235 if(disc->link < 0)
236 free(me);
237 }
238 else
239 { me->left = NULL;
240 me->right = link.left;
241 link.left = me;
242 dt->data->size += 1;
243 }
244 goto has_root;
245 }
246 }
247 else
248 { /* not found, finish up LEFT and RIGHT trees */
249 r->left = NULL;
250 l->right = NULL;
251
252 if(type&DT_NEXT)
253 goto dt_next;
254 else if(type&DT_PREV)
255 goto dt_prev;
256 else if(type&(DT_SEARCH|DT_MATCH))
257 { no_root:
258 while((t = r->left) )
259 r = t;
260 r->left = link.right;
261 dt->data->here = link.left;
262 return (type&DT_DELETE) ? obj : NULL;
263 }
264 else if(type&DT_INSERT)
265 { dt_insert:
266 if(disc->makef && (type&DT_INSERT))
267 obj = disc->makef(obj, disc);
268 if(obj)
269 { if(lk >= 0)
270 root = _DTLNK(obj,lk);
271 else
272 { root = malloc(sizeof(Dthold_t));
273 if(root)
274 ((Dthold_t*)root)->obj = obj;
275 else if(disc->makef && disc->freef &&
276 (type&DT_INSERT))
277 disc->freef(obj);
278 }
279 }
280 if(root)
281 { if(dt->data->size >= 0)
282 dt->data->size += 1;
283 goto has_root;
284 }
285 else goto no_root;
286 }
287 else if(type&DT_RENEW)
288 { root = me;
289 dt->data->size += 1;
290 goto has_root;
291 }
292 else /*if(type&DT_DELETE)*/
293 { obj = NULL;
294 goto no_root;
295 }
296 }
297
298 return NULL;
299}
300
301/* make this method available */
306
#define DT_MATCH
Definition cdt.h:140
#define _DTKEY(o, ky, sz)
Definition cdt.h:177
#define _DTDSC(dc, ky, sz, lk, cmpf)
Definition cdt.h:173
#define DT_LAST
Definition cdt.h:139
#define DT_OBAG
Definition cdt.h:126
#define DT_PREV
Definition cdt.h:135
#define _DTLNK(o, lk)
Definition cdt.h:175
#define DT_NEXT
Definition cdt.h:134
int(* Dtcompar_f)(void *, void *)
Definition cdt.h:52
#define DT_SEARCH
Definition cdt.h:133
#define dtsearch(d, o)
Definition cdt.h:191
#define DT_DELETE
Definition cdt.h:132
#define DT_CLEAR
Definition cdt.h:137
#define DT_INSERT
Definition cdt.h:131
#define DT_DETACH
Definition cdt.h:142
#define DT_RENEW
Definition cdt.h:136
#define DT_OSET
Definition cdt.h:125
#define _DTCMP(k1, k2, cmpf, sz)
Definition cdt.h:179
#define _DTOBJ(e, lk)
Definition cdt.h:176
#define DT_FIRST
Definition cdt.h:138
#define dtnext(d, o)
Definition cdt.h:188
static int cmp(const void *x, const void *y)
Definition ccomps.c:458
static int cmpf(void *key1, void *key2)
Definition dijkstra.c:81
#define RROTATE(x, y)
Definition dthdr.h:36
#define LROTATE(x, y)
Definition dthdr.h:37
#define rrotate(x, y)
Definition dthdr.h:31
#define rlink(r, x)
Definition dthdr.h:33
#define llink(l, x)
Definition dthdr.h:34
#define lrotate(x, y)
Definition dthdr.h:32
#define UNFLATTEN(dt)
Definition dthdr.h:27
static Dtmethod_t _Dtobag
Definition dttree.c:303
Dtmethod_t * Dttree
Definition dttree.c:308
static void * dttree(Dt_t *dt, void *obj, int type)
Definition dttree.c:12
Dtmethod_t _Dttree
Definition dttree.c:307
Dtmethod_t * Dtoset
ordered set (self-adjusting tree)
Definition dttree.c:304
static Dtmethod_t _Dtoset
Definition dttree.c:302
Dtmethod_t * Dtobag
ordered multiset
Definition dttree.c:305
disc key
Definition exparse.y:214
expr procedure type
Definition exparse.y:211
void * malloc(YYSIZE_T)
void free(void *)
node NULL
Definition grammar.y:149
Definition cdt.h:104
Dtdata_t * data
Definition cdt.h:106
Dtdisc_t * disc
Definition cdt.h:105
Dtmethod_t * meth
Definition cdt.h:107
Dtlink_t * here
Definition cdt.h:77
int size
Definition cdt.h:83
Dtfree_f freef
Definition cdt.h:93
Dtmake_f makef
Definition cdt.h:92
int link
Definition cdt.h:91
int type
Definition cdt.h:71