source: trunk/gsdl/packages/mg/lib/sptree.c@ 1153

Last change on this file since 1153 was 439, checked in by sjboddie, 25 years ago

renamed mg-1.3d directory mg

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 7.7 KB
Line 
1/**************************************************************************
2 *
3 * sptree.c -- Splay tree code
4 * Copyright (C) 1994 Gary Eddy, Alistair Moffat and Neil Sharman
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 *
20 * $Id: sptree.c 439 1999-08-10 21:23:37Z sjboddie $
21 *
22 **************************************************************************/
23
24
25#include "sysfuncs.h"
26#include "sptree.h"
27
28/*
29 $Log$
30 Revision 1.1 1999/08/10 21:17:04 sjboddie
31 renamed mg-1.3d directory mg
32
33 Revision 1.1 1998/11/17 09:32:45 rjmcnab
34 *** empty log message ***
35
36 * Revision 1.1 1994/08/22 00:24:50 tes
37 * Initial placement under CVS.
38 *
39 */
40
41static char *RCSID = "$Id: sptree.c 439 1999-08-10 21:23:37Z sjboddie $";
42
43#define TRACE(w)
44
45#define POOL_SIZE 1024
46
47
48typedef struct node_rec node;
49
50struct node_rec
51 {
52 node *left, *rght;
53 node *par;
54 char *datsun;
55 };
56
57struct pool
58 {
59 int length, pos;
60 struct pool *next;
61 node nodes[POOL_SIZE];
62 };
63
64static node *SP_splay ();
65
66#define CNULL ((char *) NULL)
67#define NNULL ((node *) NULL)
68#define SNULL ((Splay_Tree *) NULL)
69
70
71/*
72 * createset():
73 * allocates memory for and initialises a set.
74 *
75 * Accesses outside variables: none
76 *
77 * Return value...: none
78 */
79
80Splay_Tree *
81SP_createset (int (*cmp) (void *, void *))
82{
83 Splay_Tree *S;
84
85 if (!(S = (Splay_Tree *) malloc (sizeof (Splay_Tree))))
86 return (SNULL);
87 S->cmp = cmp;
88 S->root = CNULL;
89 S->no_of_items = 0;
90 S->mem_in_use = sizeof (Splay_Tree);
91 S->pool = NULL;
92 S->pool_chunks = 1024;
93 return S;
94} /* createset() */
95
96
97
98static node *
99SP_get_node (Splay_Tree * S)
100{
101 struct pool *p = S->pool;
102 if (!p || p->pos == p->length)
103 {
104 p = malloc (sizeof (struct pool));
105 if (!p)
106 return NULL;
107 S->mem_in_use += sizeof (struct pool);
108 p->length = POOL_SIZE;
109 p->pos = 0;
110 p->next = S->pool;
111 S->pool = p;
112 }
113 return &(p->nodes[p->pos++]);
114}
115
116
117
118/*
119 * SP_freeset():
120 * free the memory allocated to a splay tree. Note this Does not
121 * free the data in the tree you must do this yourself.
122 *
123 * Accesses outside variables: none
124 *
125 * Return value...: none
126 */
127
128void
129SP_freeset (Splay_Tree * S)
130{
131 while (S->pool)
132 {
133 struct pool *p = S->pool;
134 S->pool = p->next;
135 free (p);
136 }
137 free (S);
138}
139
140
141/*
142 * insert():
143 * inserts the item given into the set given in the order
144 * specified by the comparison function in the set
145 * definition.
146 *
147 * Accesses outside variables: none
148 *
149 * Return value...: none
150 */
151
152
153void *
154SP_insert (void *item, Splay_Tree * S)
155{
156 int dir = 0;
157 register node *curr, *prev;
158 node *tmp;
159
160 prev = NNULL;
161 curr = (node *) S->root;
162 for (; curr;)
163 {
164 prev = curr;
165 dir = S->cmp (item, curr->datsun);
166 if (dir < 0)
167 curr = curr->left;
168 else
169 curr = curr->rght;
170 }
171 if (!(tmp = SP_get_node (S)))
172 return NULL;
173 tmp->datsun = item;
174
175 if (prev == NNULL)
176 S->root = (char *) tmp;
177 else if (dir < 0)
178 prev->left = tmp;
179 else
180 prev->rght = tmp;
181
182 tmp->par = prev;
183 tmp->left = NNULL;
184 tmp->rght = NNULL;
185 S->no_of_items++;
186 S->root = (char *) SP_splay (tmp);
187 return (tmp->datsun);
188} /* insert() */
189
190/*
191 * get_first():
192 * returns a pointer to the first item in the set. If the set
193 * is empty a NULL pointer is returned.
194 *
195 * Accesses outside variables: none
196 */
197
198void *
199SP_get_first (Splay_Tree * S)
200{
201 node *curr, *prev;
202
203 for (curr = (node *) S->root, prev = NNULL; curr;
204 prev = curr, curr = curr->left)
205 ; /* NULLBODY */
206
207 if (prev)
208 S->root = (char *) SP_splay (prev);
209 return (prev ? prev->datsun : CNULL);
210} /* get_first() */
211
212/*
213 * get_next():
214 * returns the in-order successor of the currently fingered
215 * item of the set. If no item is fingered or if there is
216 * no in-order successor a NULL pointer is returned.
217 *
218 * Accesses outside variables: none
219 */
220
221void *
222SP_get_next (Splay_Tree * S)
223{
224 node *curr, *prev;
225
226 curr = (node *) S->root;
227 if (!curr || !curr->rght)
228 return (CNULL);
229
230 for (prev = curr, curr = curr->rght; curr;
231 prev = curr, curr = curr->left)
232 ; /* NULLBODY */
233
234 if (prev)
235 S->root = (char *) SP_splay (prev);
236 return (prev ? prev->datsun : CNULL);
237} /* get_next() */
238
239/*
240 * deletemin():
241 * removes the first element in the set and returns a
242 * pointer to it. If the set is empty a NULL pointer
243 * is returned.
244 *
245 * Accesses outside variables: none
246 */
247
248void *
249SP_deletemin (Splay_Tree * S)
250{
251 node *tmp;
252 char *dat;
253
254 dat = SP_get_first (S);
255 if (dat)
256 {
257 tmp = (node *) S->root;
258 S->root = (char *) tmp->rght;
259 if (S->root)
260 ((node *) S->root)->par = NULL;
261 }
262 S->no_of_items--;
263 return dat;
264} /* deletemin() */
265
266
267/*
268 * member():
269 * searches the given set for an item which matches (has
270 * the same key) and returns a pointer to a copy of that item.
271 * If no matching item is found a NULL pointer is
272 * returned.
273 *
274 * Accesses outside variables: none
275 */
276
277void *
278SP_member (void *dat, Splay_Tree * S)
279{
280 register node *curr;
281 register int dir;
282 static int calls = 0;
283
284 TRACE ("in member");
285 for (curr = (node *) S->root; curr;)
286 {
287 TRACE ("call to cmp");
288 dir = S->cmp (dat, curr->datsun);
289 TRACE ("out of cmp");
290 if (dir < 0)
291 curr = curr->left;
292 else if (dir > 0)
293 curr = curr->rght;
294 else
295 {
296 /* splay occasionaly to speed up execution */
297 if ((calls++ % 4) == 0 && curr)
298 S->root = (char *) SP_splay (curr);
299 TRACE ("out of member");
300 return (curr->datsun);
301 }
302 }
303 TRACE ("out of member");
304 return (CNULL);
305} /* member() */
306
307#define ROTATEL(p,q) \
308 do{ \
309 p->par = q->par; \
310 q->par = p; \
311 q->rght = p->left; \
312 if(q->rght) \
313 q->rght->par = q; \
314 p->left = q; \
315 if(p->par) \
316 if(q == p->par->left) \
317 p->par->left = p; \
318 else \
319 p->par->rght = p; \
320 }while(0)
321
322#define ROTATER(p,q) \
323 do{ \
324 p->par = q->par; \
325 q->par = p; \
326 q->left = p->rght; \
327 if(q->left) \
328 q->left->par = q; \
329 p->rght = q; \
330 if(p->par) \
331 if(q == p->par->left) \
332 p->par->left = p; \
333 else \
334 p->par->rght = p; \
335 }while(0)
336
337
338/*
339 * splay():
340 * i
341 *
342 * Accesses outside variables: i
343 *
344 * Return value...: i
345 */
346
347static node *
348SP_splay (p)
349 register node *p;
350{
351 register node *q, *g;
352
353 q = p->par;
354 /* splay the tree about p */
355 while (q != NNULL)
356 {
357 g = q->par;
358 if (p == q->left)
359 {
360 if (g == NNULL)
361 ROTATER (p, q);
362 else if (q == g->left)
363 {
364 ROTATER (q, g);
365 ROTATER (p, q);
366 }
367 else
368 {
369 ROTATER (p, q);
370 ROTATEL (p, g);
371 }
372 }
373 else
374 {
375 if (g == NNULL)
376 ROTATEL (p, q);
377 else if (q == g->rght)
378 {
379 ROTATEL (q, g);
380 ROTATEL (p, q);
381 }
382 else
383 {
384 ROTATEL (p, q);
385 ROTATER (p, g);
386 }
387 }
388 q = p->par;
389 }
390 return (p);
391}
Note: See TracBrowser for help on using the repository browser.