source: trunk/gsdl3/src/packages/mg/lib/sptree.c@ 3745

Last change on this file since 3745 was 3745, checked in by mdewsnip, 21 years ago

Addition of MG package for search and retrieval

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