source: trunk/src/zAVLTree.c@ 420

Last change on this file since 420 was 383, checked in by katerina, 13 years ago

Fix for ticket #281 (warnings from clang static analyzer).

File size: 12.9 KB
Line 
1/*
2 * zAVLTree.c: Source code for zAVLTrees.
3 * Copyright (C) 1998,2001 Michael H. Buselli
4 * This is version 0.1.3 (alpha).
5 * Generated from $Id: xAVLTree.c.sh,v 1.5 2001/06/07 06:58:28 cosine Exp $
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the Free
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *
21 * The author of this library can be reached at the following address:
22 * Michael H. Buselli
23 * 30051 N. Waukegan Rd. Apt. 103
24 * Lake Bluff, IL 60044-5412
25 *
26 * Or you can send email to <cosine@cosine.org>.
27 * The official web page for this product is:
28 * http://www.cosine.org/project/AVLTree/
29 */
30
31#include <stdlib.h>
32#include <string.h>
33#include "zAVLTree.h"
34
35/* Wed Nov 23 17:57:42 CET 2005 rw: introduce third argument in
36 * zAVLCloseSearchNode() to avoid redundant strcmp
37 */
38static zAVLNode *zAVLCloseSearchNode (zAVLTree const *avltree, zAVLKey key,
39 int * ok);
40static void zAVLRebalanceNode (zAVLTree *avltree, zAVLNode *avlnode);
41static void zAVLFreeBranch (zAVLNode *avlnode, void (freeitem)(void *item));
42static void zAVLFillVacancy (zAVLTree *avltree,
43 zAVLNode *origparent, zAVLNode **superparent,
44 zAVLNode *left, zAVLNode *right);
45
46#define MAX(x, y) ((x) > (y) ? (x) : (y))
47#define MIN(x, y) ((x) < (y) ? (x) : (y))
48#define L_DEPTH(n) ((n)->left ? (n)->left->depth : 0)
49#define R_DEPTH(n) ((n)->right ? (n)->right->depth : 0)
50#define CALC_DEPTH(n) (MAX(L_DEPTH(n), R_DEPTH(n)) + 1)
51
52#define ZAVL_OK 1
53#define ZAVL_NO 0
54
55/* The comparison function. Was a macro, but this allows for more
56 * flexibility (non-string keys). The key is a (void *) now, and
57 * the type is stored in the zAVLTree struct. Oct 21, 2011, rw
58 */
59static int zAVLKey_cmp(const zAVLTree * tree, zAVLKey a, zAVLKey b)
60{
61 if (tree->keytype == zAVL_KEY_STRING)
62 {
63 return (strcmp((char*)a, (char *)b));
64 }
65 else /* zAVL_KEY_INT */
66 {
67 int x = *((int *)a);
68 int y = *((int *)b);
69
70 if (x > y) return 1;
71 else if (x < y) return -1;
72 else return 0;
73 }
74}
75
76/*
77 * AVLAllocTree:
78 * Allocate memory for a new AVL tree and set the getkey function for
79 * that tree. The getkey function should take an item and return an
80 * AVLKey that is to be used for indexing this object in the AVL tree.
81 * On success, a pointer to the malloced AVLTree is returned. If there
82 * was a malloc failure, then NULL is returned.
83 */
84zAVLTree *zAVLAllocTree (zAVLKey (*getkey)(void const *item), int keytype)
85{
86 zAVLTree *rc;
87
88 rc = malloc(sizeof(zAVLTree));
89 if (rc == NULL)
90 return NULL;
91
92 rc->top = NULL;
93 rc->count = 0;
94 rc->getkey = getkey;
95 rc->keytype = keytype;
96 return rc;
97}
98
99
100/*
101 * AVLFreeTree:
102 * Free all memory used by this AVL tree. If freeitem is not NULL, then
103 * it is assumed to be a destructor for the items reference in the AVL
104 * tree, and they are deleted as well.
105 */
106void zAVLFreeTree (zAVLTree *avltree, void (freeitem)(void *item))
107{
108 if (NULL == avltree) /* R.W. Mon Nov 19 21:15:44 CET 2001 */
109 return;
110 if (avltree->top)
111 zAVLFreeBranch(avltree->top, freeitem);
112 free(avltree);
113}
114
115
116/*
117 * AVLInsert:
118 * Create a new node and insert an item there.
119 *
120 * Returns 0 on success,
121 * -1 on malloc failure,
122 * 3 if duplicate key.
123 */
124int zAVLInsert (zAVLTree *avltree, void *item)
125{
126 zAVLNode *newnode;
127 zAVLNode *node;
128 zAVLNode *balnode;
129 zAVLNode *nextbalnode;
130 int ok;
131
132 newnode = malloc(sizeof(zAVLNode));
133 if (newnode == NULL)
134 return -1;
135
136 newnode->key = avltree->getkey(item);
137 newnode->item = item;
138 newnode->depth = 1;
139 newnode->left = NULL;
140 newnode->right = NULL;
141 newnode->parent = NULL;
142
143 if (avltree->top != NULL) {
144 node = zAVLCloseSearchNode(avltree, newnode->key, &ok);
145
146 if (ok == ZAVL_OK) { /* exists already */
147 free(newnode);
148 return 3;
149 }
150
151 newnode->parent = node;
152
153 if (zAVLKey_cmp(avltree, newnode->key, node->key) < 0) {
154 node->left = newnode;
155 node->depth = CALC_DEPTH(node);
156 }
157
158 else {
159 node->right = newnode;
160 node->depth = CALC_DEPTH(node);
161 }
162
163 for (balnode = node->parent; balnode; balnode = nextbalnode) {
164 nextbalnode = balnode->parent;
165 zAVLRebalanceNode(avltree, balnode);
166 }
167 }
168
169 else {
170 avltree->top = newnode;
171 }
172
173 avltree->count++;
174 return 0;
175}
176
177
178/*
179 * zAVLSearch:
180 * Return a pointer to the item with the given key in the AVL tree. If
181 * no such item is in the tree, then NULL is returned.
182 */
183void *zAVLSearch (zAVLTree const *avltree, zAVLKey key)
184{
185 zAVLNode *node;
186 int ok;
187
188 if (NULL == avltree) /* R.W. Mon Nov 19 21:15:44 CET 2001 */
189 return NULL;
190
191 node = zAVLCloseSearchNode(avltree, key, &ok);
192
193 if (node && ok == ZAVL_OK)
194 return node->item;
195
196 return NULL;
197}
198
199
200/*
201 * zAVLDelete:
202 * Deletes the node with the given key. Does not delete the item at
203 * that key. Returns 0 on success and -1 if a node with the given key
204 * does not exist.
205 */
206int zAVLDelete (zAVLTree *avltree, zAVLKey key)
207{
208 zAVLNode *avlnode;
209 zAVLNode *origparent;
210 zAVLNode **superparent;
211 int ok;
212
213 avlnode = zAVLCloseSearchNode(avltree, key, &ok);
214 if (avlnode == NULL || ok == ZAVL_NO) /* does not exist */
215 return -1;
216
217 origparent = avlnode->parent;
218
219 if (origparent) {
220 if (zAVLKey_cmp(avltree, avlnode->key, avlnode->parent->key) < 0)
221 superparent = &(avlnode->parent->left);
222 else
223 superparent = &(avlnode->parent->right);
224 }
225 else
226 superparent = &(avltree->top);
227
228 zAVLFillVacancy(avltree, origparent, superparent,
229 avlnode->left, avlnode->right);
230 free(avlnode);
231 avltree->count--;
232 return 0;
233}
234
235
236/*
237 * zAVLFirst:
238 * Initializes an zAVLCursor object and returns the item with the lowest
239 * key in the zAVLTree.
240 */
241void *zAVLFirst (zAVLCursor *avlcursor, zAVLTree const *avltree)
242{
243 const zAVLNode *avlnode;
244
245 if (NULL == avltree) /* R.W. Mon Nov 19 21:15:44 CET 2001 */
246 return NULL;
247
248 avlcursor->avltree = avltree;
249
250 if (avltree->top == NULL) {
251 avlcursor->curnode = NULL;
252 return NULL;
253 }
254
255 for (avlnode = avltree->top;
256 avlnode->left != NULL;
257 avlnode = avlnode->left);
258 avlcursor->curnode = avlnode;
259 return avlnode->item;
260}
261
262
263/*
264 * zAVLNext:
265 * Called after an zAVLFirst() call, this returns the item with the least
266 * key that is greater than the last item returned either by zAVLFirst()
267 * or a previous invokation of this function.
268 */
269void *zAVLNext (zAVLCursor *avlcursor)
270{
271 const zAVLNode *avlnode;
272
273 avlnode = avlcursor->curnode;
274
275 if (avlnode->right != NULL) {
276 for (avlnode = avlnode->right;
277 avlnode->left != NULL;
278 avlnode = avlnode->left);
279 avlcursor->curnode = avlnode;
280 return avlnode->item;
281 }
282
283 while (avlnode->parent && avlnode->parent->left != avlnode) {
284 avlnode = avlnode->parent;
285 }
286
287 if (avlnode->parent == NULL) {
288 avlcursor->curnode = NULL;
289 return NULL;
290 }
291
292 avlcursor->curnode = avlnode->parent;
293 return avlnode->parent->item;
294}
295
296
297/*
298 * zAVLCloseSearchNode:
299 * Return a pointer to the node closest to the given key.
300 * Returns NULL if the AVL tree is empty.
301 */
302static zAVLNode *zAVLCloseSearchNode (zAVLTree const *avltree, zAVLKey key,
303 int * ok)
304{
305 zAVLNode *node;
306
307 *ok = ZAVL_NO;
308
309 node = avltree->top;
310
311 if (!node)
312 return NULL;
313
314 for (;;) {
315 if (!zAVLKey_cmp(avltree, node->key, key))
316 {
317 *ok = ZAVL_OK;
318 return node;
319 }
320
321 if (zAVLKey_cmp(avltree, node->key, key) < 0) {
322 if (node->right)
323 node = node->right;
324 else
325 return node;
326 }
327
328 else {
329 if (node->left)
330 node = node->left;
331 else
332 return node;
333 }
334 }
335}
336
337
338/*
339 * zAVLRebalanceNode:
340 * Rebalances the AVL tree if one side becomes too heavy. This function
341 * assumes that both subtrees are AVL trees with consistant data. This
342 * function has the additional side effect of recalculating the depth of
343 * the tree at this node. It should be noted that at the return of this
344 * function, if a rebalance takes place, the top of this subtree is no
345 * longer going to be the same node.
346 */
347static void zAVLRebalanceNode (zAVLTree *avltree, zAVLNode *avlnode)
348{
349 long depthdiff;
350 zAVLNode *child;
351 zAVLNode *gchild;
352 zAVLNode *origparent;
353 zAVLNode **superparent;
354
355 origparent = avlnode->parent;
356
357 if (origparent) {
358 if (zAVLKey_cmp(avltree, avlnode->key, avlnode->parent->key) < 0)
359 superparent = &(avlnode->parent->left);
360 else
361 superparent = &(avlnode->parent->right);
362 }
363 else
364 superparent = &(avltree->top);
365
366 depthdiff = R_DEPTH(avlnode) - L_DEPTH(avlnode);
367
368 if (depthdiff <= -2 && avlnode->left) {
369 child = avlnode->left;
370
371 if (L_DEPTH(child) >= R_DEPTH(child)) {
372 avlnode->left = child->right;
373 if (avlnode->left != NULL)
374 avlnode->left->parent = avlnode;
375 avlnode->depth = CALC_DEPTH(avlnode);
376 child->right = avlnode;
377 if (child->right != NULL)
378 child->right->parent = child;
379 child->depth = CALC_DEPTH(child);
380 *superparent = child;
381 child->parent = origparent;
382 }
383
384 else {
385 gchild = child->right;
386 if (gchild)
387 {
388 avlnode->left = gchild->right;
389 if (avlnode->left != NULL)
390 avlnode->left->parent = avlnode;
391 avlnode->depth = CALC_DEPTH(avlnode);
392 child->right = gchild->left;
393 if (child->right != NULL)
394 child->right->parent = child;
395 child->depth = CALC_DEPTH(child);
396 gchild->right = avlnode;
397 if (gchild->right != NULL)
398 gchild->right->parent = gchild;
399 gchild->left = child;
400 if (gchild->left != NULL)
401 gchild->left->parent = gchild;
402 gchild->depth = CALC_DEPTH(gchild);
403 *superparent = gchild;
404 gchild->parent = origparent;
405 }
406 }
407 }
408
409 else if (depthdiff >= 2 && avlnode->right) {
410 child = avlnode->right;
411
412 if (R_DEPTH(child) >= L_DEPTH(child)) {
413 avlnode->right = child->left;
414 if (avlnode->right != NULL)
415 avlnode->right->parent = avlnode;
416 avlnode->depth = CALC_DEPTH(avlnode);
417 child->left = avlnode;
418 if (child->left != NULL)
419 child->left->parent = child;
420 child->depth = CALC_DEPTH(child);
421 *superparent = child;
422 child->parent = origparent;
423 }
424
425 else {
426 gchild = child->left;
427 if (gchild)
428 {
429 avlnode->right = gchild->left;
430 if (avlnode->right != NULL)
431 avlnode->right->parent = avlnode;
432 avlnode->depth = CALC_DEPTH(avlnode);
433 child->left = gchild->right;
434 if (child->left != NULL)
435 child->left->parent = child;
436 child->depth = CALC_DEPTH(child);
437 gchild->left = avlnode;
438 if (gchild->left != NULL)
439 gchild->left->parent = gchild;
440 gchild->right = child;
441 if (gchild->right != NULL)
442 gchild->right->parent = gchild;
443 gchild->depth = CALC_DEPTH(gchild);
444 *superparent = gchild;
445 gchild->parent = origparent;
446 }
447 }
448 }
449
450 else {
451 avlnode->depth = CALC_DEPTH(avlnode);
452 }
453}
454
455
456/*
457 * zAVLFreeBranch:
458 * Free memory used by this node and its item. If the freeitem argument
459 * is not NULL, then that function is called on the items to free their
460 * memory as well. In other words, the freeitem function is a
461 * destructor for the items in the tree.
462 */
463static void zAVLFreeBranch (zAVLNode *avlnode, void (freeitem)(void *item))
464{
465 if (avlnode->left)
466 zAVLFreeBranch(avlnode->left, freeitem);
467 if (avlnode->right)
468 zAVLFreeBranch(avlnode->right, freeitem);
469 if (freeitem)
470 freeitem(avlnode->item);
471 free(avlnode);
472}
473
474
475/*
476 * zAVLFillVacancy:
477 * Given a vacancy in the AVL tree by it's parent, children, and parent
478 * component pointer, fill that vacancy.
479 */
480static void zAVLFillVacancy (zAVLTree *avltree,
481 zAVLNode *origparent, zAVLNode **superparent,
482 zAVLNode *left, zAVLNode *right)
483{
484 zAVLNode *avlnode;
485 zAVLNode *balnode;
486 zAVLNode *nextbalnode;
487
488 if (left == NULL) {
489 if (right)
490 right->parent = origparent;
491
492 *superparent = right;
493 balnode = origparent;
494 }
495
496 else {
497 for (avlnode = left; avlnode->right != NULL; avlnode = avlnode->right);
498
499 if (avlnode == left) {
500 balnode = avlnode;
501 }
502 else {
503 balnode = avlnode->parent;
504 balnode->right = avlnode->left;
505 if (balnode->right != NULL)
506 balnode->right->parent = balnode;
507 avlnode->left = left;
508 left->parent = avlnode;
509 }
510
511 avlnode->right = right;
512 if (right != NULL)
513 right->parent = avlnode;
514 *superparent = avlnode;
515 avlnode->parent = origparent;
516 }
517
518 for (; balnode; balnode = nextbalnode) {
519 nextbalnode = balnode->parent;
520 zAVLRebalanceNode(avltree, balnode);
521 }
522}
Note: See TracBrowser for help on using the repository browser.