source: main/branches/64_bit_Greenstone/greenstone2/common-src/indexers/mg/lib/sptree.c@ 23508

Last change on this file since 23508 was 23508, checked in by sjm84, 13 years ago

Committing 64 bit changes into the branch

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