OPAL (Object Oriented Parallel Accelerator Library) 2022.1
OPAL
avl.cpp
Go to the documentation of this file.
1/*****************************************************************************
2
3 avl.c - Source code for the AVL-tree library.
4
5 Copyright (C) 1998 Michael H. Buselli <cosine@cosine.org>
6 Copyright (C) 2000-2002 Wessel Dankers <wsl@nl.linux.org>
7
8 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Lesser General Public
10 License as published by the Free Software Foundation; either
11 version 2.1 of the License, or (at your option) any later version.
12
13 This library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public
19 License along with this library; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
22 Augmented AVL-tree. Original by Michael H. Buselli <cosine@cosine.org>.
23
24 Modified by Wessel Dankers <wsl@nl.linux.org> to add a bunch of bloat to
25 the sourcecode, change the interface and squash a few bugs.
26 Mail him if you find new bugs.
27
28*****************************************************************************/
29
30#include <stdio.h>
31#include <stdlib.h>
32#include <errno.h>
33#include "avl.h"
34
35static void avl_rebalance(avl_tree_t *, avl_node_t *);
36
37#ifdef AVL_COUNT
38#define NODE_COUNT(n) ((n) ? (n)->count : 0)
39#define L_COUNT(n) (NODE_COUNT((n)->left))
40#define R_COUNT(n) (NODE_COUNT((n)->right))
41#define CALC_COUNT(n) (L_COUNT(n) + R_COUNT(n) + 1)
42#endif
43
44#ifdef AVL_DEPTH
45#define NODE_DEPTH(n) ((n) ? (n)->depth : 0)
46#define L_DEPTH(n) (NODE_DEPTH((n)->left))
47#define R_DEPTH(n) (NODE_DEPTH((n)->right))
48#define CALC_DEPTH(n) ((L_DEPTH(n)>R_DEPTH(n)?L_DEPTH(n):R_DEPTH(n)) + 1)
49#endif
50
51#ifndef AVL_DEPTH
52/* Also known as ffs() (from BSD) */
53static int lg(unsigned int u) {
54 int r = 1;
55 if(!u) return 0;
56 if(u & 0xffff0000) { u >>= 16; r += 16; }
57 if(u & 0x0000ff00) { u >>= 8; r += 8; }
58 if(u & 0x000000f0) { u >>= 4; r += 4; }
59 if(u & 0x0000000c) { u >>= 2; r += 2; }
60 if(u & 0x00000002) r++;
61 return r;
62}
63#endif
64
65static int avl_check_balance(avl_node_t *avlnode) {
66#ifdef AVL_DEPTH
67 int d;
68 d = R_DEPTH(avlnode) - L_DEPTH(avlnode);
69 return d<-1?-1:d>1?1:0;
70#else
71/* int d;
72 * d = lg(R_COUNT(avlnode)) - lg(L_COUNT(avlnode));
73 * d = d<-1?-1:d>1?1:0;
74 */
75#ifdef AVL_COUNT
76 int pl, r;
77
78 pl = lg(L_COUNT(avlnode));
79 r = R_COUNT(avlnode);
80
81 if(r>>pl+1)
82 return 1;
83 if(pl<2 || r>>pl-2)
84 return 0;
85 return -1;
86#else
87#error No balancing possible.
88#endif
89#endif
90}
91
92#ifdef AVL_COUNT
93unsigned int avl_count(const avl_tree_t *avltree) {
94 return NODE_COUNT(avltree->top);
95}
96
97avl_node_t *avl_at(const avl_tree_t *avltree, unsigned int index) {
98 avl_node_t *avlnode;
99 unsigned int c;
100
101 avlnode = avltree->top;
102
103 while(avlnode) {
104 c = L_COUNT(avlnode);
105
106 if(index < c) {
107 avlnode = avlnode->left;
108 } else if(index > c) {
109 avlnode = avlnode->right;
110 index -= c+1;
111 } else {
112 return avlnode;
113 }
114 }
115 return NULL;
116}
117
118unsigned int avl_index(const avl_node_t *avlnode) {
119 avl_node_t *next;
120 unsigned int c;
121
122 c = L_COUNT(avlnode);
123
124 while((next = avlnode->parent)) {
125 if(avlnode == next->right)
126 c += L_COUNT(next) + 1;
127 avlnode = next;
128 }
129
130 return c;
131}
132#endif
133
134int avl_search_closest(const avl_tree_t *avltree, const void *item, avl_node_t **avlnode) {
135 avl_node_t *node;
137 int c;
138
139 if(!avlnode)
140 avlnode = &node;
141
142 node = avltree->top;
143
144 if(!node)
145 return *avlnode = NULL, 0;
146
147 cmp = avltree->cmp;
148
149 for(;;) {
150 c = cmp(item, node->item);
151
152 if(c < 0) {
153 if(node->left)
154 node = node->left;
155 else
156 return *avlnode = node, -1;
157 } else if(c > 0) {
158 if(node->right)
159 node = node->right;
160 else
161 return *avlnode = node, 1;
162 } else {
163 return *avlnode = node, 0;
164 }
165 }
166}
167
168/*
169 * avl_search:
170 * Return a pointer to a node with the given item in the tree.
171 * If no such item is in the tree, then NULL is returned.
172 */
173avl_node_t *avl_search(const avl_tree_t *avltree, const void *item) {
174 avl_node_t *node;
175 return avl_search_closest(avltree, item, &node) ? NULL : node;
176}
177
179 if(rc) {
180 rc->head = NULL;
181 rc->tail = NULL;
182 rc->top = NULL;
183 rc->cmp = cmp;
184 rc->freeitem = freeitem;
185 }
186 return rc;
187}
188
190 return avl_init_tree((avl_tree_t*)malloc(sizeof(avl_tree_t)), cmp, freeitem);
191}
192
194 avltree->top = avltree->head = avltree->tail = NULL;
195}
196
198 avl_node_t *node, *next;
199 avl_freeitem_t freeitem;
200
201 freeitem = avltree->freeitem;
202
203 for(node = avltree->head; node; node = next) {
204 next = node->next;
205 if(freeitem)
206 freeitem(node->item);
207 free(node);
208 }
209 return avl_clear_tree(avltree);
210}
211
212/*
213 * avl_free_tree:
214 * Free all memory used by this tree. If freeitem is not NULL, then
215 * it is assumed to be a destructor for the items referenced in the avl_
216 * tree, and they are deleted as well.
217 */
218void avl_free_tree(avl_tree_t *avltree) {
219 avl_free_nodes(avltree);
220 free(avltree);
221}
222
223static void avl_clear_node(avl_node_t *newnode) {
224 newnode->left = newnode->right = NULL;
225 #ifdef AVL_COUNT
226 newnode->count = 1;
227 #endif
228 #ifdef AVL_DEPTH
229 newnode->depth = 1;
230 #endif
231}
232
233avl_node_t *avl_init_node(avl_node_t *newnode, void *item) {
234 if(newnode) {
235 avl_clear_node(newnode);
236 newnode->item = item;
237 }
238 return newnode;
239}
240
242 avl_clear_node(newnode);
243 newnode->prev = newnode->next = newnode->parent = NULL;
244 avltree->head = avltree->tail = avltree->top = newnode;
245 return newnode;
246}
247
249 if(!node)
250 return avltree->tail
251 ? avl_insert_after(avltree, avltree->tail, newnode)
252 : avl_insert_top(avltree, newnode);
253
254 if(node->left)
255 return avl_insert_after(avltree, node->prev, newnode);
256
257 avl_clear_node(newnode);
258
259 newnode->next = node;
260 newnode->parent = node;
261
262 newnode->prev = node->prev;
263 if(node->prev)
264 node->prev->next = newnode;
265 else
266 avltree->head = newnode;
267 node->prev = newnode;
268
269 node->left = newnode;
270 avl_rebalance(avltree, node);
271 return newnode;
272}
273
275 if(!node)
276 return avltree->head
277 ? avl_insert_before(avltree, avltree->head, newnode)
278 : avl_insert_top(avltree, newnode);
279
280 if(node->right)
281 return avl_insert_before(avltree, node->next, newnode);
282
283 avl_clear_node(newnode);
284
285 newnode->prev = node;
286 newnode->parent = node;
287
288 newnode->next = node->next;
289 if(node->next)
290 node->next->prev = newnode;
291 else
292 avltree->tail = newnode;
293 node->next = newnode;
294
295 node->right = newnode;
296 avl_rebalance(avltree, node);
297 return newnode;
298}
299
301 avl_node_t *node;
302
303 if(!avltree->top)
304 return avl_insert_top(avltree, newnode);
305
306 switch(avl_search_closest(avltree, newnode->item, &node)) {
307 case -1:
308 return avl_insert_before(avltree, node, newnode);
309 case 1:
310 return avl_insert_after(avltree, node, newnode);
311 }
312
313 return NULL;
314}
315
316/*
317 * avl_insert:
318 * Create a new node and insert an item there.
319 * Returns the new node on success or NULL if no memory could be allocated.
320 */
321avl_node_t *avl_insert(avl_tree_t *avltree, void *item) {
322 avl_node_t *newnode;
323
324 newnode = avl_init_node((avl_node_t*)malloc(sizeof(avl_node_t)), item);
325 if(newnode) {
326 if(avl_insert_node(avltree, newnode))
327 return newnode;
328 free(newnode);
329 errno = EEXIST;
330 }
331 return NULL;
332}
333
334/*
335 * avl_unlink_node:
336 * Removes the given node. Does not delete the item at that node.
337 * The item of the node may be freed before calling avl_unlink_node.
338 * (In other words, it is not referenced by this function.)
339 */
340void avl_unlink_node(avl_tree_t *avltree, avl_node_t *avlnode) {
341 avl_node_t *parent;
342 avl_node_t **superparent;
343 avl_node_t *subst, *left, *right;
344 avl_node_t *balnode;
345
346 if(avlnode->prev)
347 avlnode->prev->next = avlnode->next;
348 else
349 avltree->head = avlnode->next;
350
351 if(avlnode->next)
352 avlnode->next->prev = avlnode->prev;
353 else
354 avltree->tail = avlnode->prev;
355
356 parent = avlnode->parent;
357
358 superparent = parent
359 ? avlnode == parent->left ? &parent->left : &parent->right
360 : &avltree->top;
361
362 left = avlnode->left;
363 right = avlnode->right;
364 if(!left) {
365 *superparent = right;
366 if(right)
367 right->parent = parent;
368 balnode = parent;
369 } else if(!right) {
370 *superparent = left;
371 left->parent = parent;
372 balnode = parent;
373 } else {
374 subst = avlnode->prev;
375 if(subst == left) {
376 balnode = subst;
377 } else {
378 balnode = subst->parent;
379 balnode->right = subst->left;
380 if(balnode->right)
381 balnode->right->parent = balnode;
382 subst->left = left;
383 left->parent = subst;
384 }
385 subst->right = right;
386 subst->parent = parent;
387 right->parent = subst;
388 *superparent = subst;
389 }
390
391 avl_rebalance(avltree, balnode);
392}
393
394void *avl_delete_node(avl_tree_t *avltree, avl_node_t *avlnode) {
395 void *item = NULL;
396 if(avlnode) {
397 item = avlnode->item;
398 avl_unlink_node(avltree, avlnode);
399 if(avltree->freeitem)
400 avltree->freeitem(item);
401 free(avlnode);
402 }
403 return item;
404}
405
406void *avl_delete(avl_tree_t *avltree, const void *item) {
407 return avl_delete_node(avltree, avl_search(avltree, item));
408}
409
411 avl_node_t *oldnode = NULL, *node;
412
413 if(!avltree || !newnode)
414 return NULL;
415
416 node = newnode->prev;
417 if(node) {
418 oldnode = node->next;
419 node->next = newnode;
420 } else {
421 avltree->head = newnode;
422 }
423
424 node = newnode->next;
425 if(node) {
426 oldnode = node->prev;
427 node->prev = newnode;
428 } else {
429 avltree->tail = newnode;
430 }
431
432 node = newnode->parent;
433 if(node) {
434 if(node->left == oldnode)
435 node->left = newnode;
436 else
437 node->right = newnode;
438 } else {
439 oldnode = avltree->top;
440 avltree->top = newnode;
441 }
442
443 return oldnode;
444}
445
446/*
447 * avl_rebalance:
448 * Rebalances the tree if one side becomes too heavy. This function
449 * assumes that both subtrees are AVL-trees with consistant data. The
450 * function has the additional side effect of recalculating the count of
451 * the tree at this node. It should be noted that at the return of this
452 * function, if a rebalance takes place, the top of this subtree is no
453 * longer going to be the same node.
454 */
455void avl_rebalance(avl_tree_t *avltree, avl_node_t *avlnode) {
456 avl_node_t *child;
457 avl_node_t *gchild;
458 avl_node_t *parent;
459 avl_node_t **superparent;
460
461 parent = avlnode;
462
463 while(avlnode) {
464 parent = avlnode->parent;
465
466 superparent = parent
467 ? avlnode == parent->left ? &parent->left : &parent->right
468 : &avltree->top;
469
470 switch(avl_check_balance(avlnode)) {
471 case -1:
472 child = avlnode->left;
473 #ifdef AVL_DEPTH
474 if(L_DEPTH(child) >= R_DEPTH(child)) {
475 #else
476 #ifdef AVL_COUNT
477 if(L_COUNT(child) >= R_COUNT(child)) {
478 #else
479 #error No balancing possible.
480 #endif
481 #endif
482 avlnode->left = child->right;
483 if(avlnode->left)
484 avlnode->left->parent = avlnode;
485 child->right = avlnode;
486 avlnode->parent = child;
487 *superparent = child;
488 child->parent = parent;
489 #ifdef AVL_COUNT
490 avlnode->count = CALC_COUNT(avlnode);
491 child->count = CALC_COUNT(child);
492 #endif
493 #ifdef AVL_DEPTH
494 avlnode->depth = CALC_DEPTH(avlnode);
495 child->depth = CALC_DEPTH(child);
496 #endif
497 } else {
498 gchild = child->right;
499 avlnode->left = gchild->right;
500 if(avlnode->left)
501 avlnode->left->parent = avlnode;
502 child->right = gchild->left;
503 if(child->right)
504 child->right->parent = child;
505 gchild->right = avlnode;
506 if(gchild->right)
507 gchild->right->parent = gchild;
508 gchild->left = child;
509 if(gchild->left)
510 gchild->left->parent = gchild;
511 *superparent = gchild;
512 gchild->parent = parent;
513 #ifdef AVL_COUNT
514 avlnode->count = CALC_COUNT(avlnode);
515 child->count = CALC_COUNT(child);
516 gchild->count = CALC_COUNT(gchild);
517 #endif
518 #ifdef AVL_DEPTH
519 avlnode->depth = CALC_DEPTH(avlnode);
520 child->depth = CALC_DEPTH(child);
521 gchild->depth = CALC_DEPTH(gchild);
522 #endif
523 }
524 break;
525 case 1:
526 child = avlnode->right;
527 #ifdef AVL_DEPTH
528 if(R_DEPTH(child) >= L_DEPTH(child)) {
529 #else
530 #ifdef AVL_COUNT
531 if(R_COUNT(child) >= L_COUNT(child)) {
532 #else
533 #error No balancing possible.
534 #endif
535 #endif
536 avlnode->right = child->left;
537 if(avlnode->right)
538 avlnode->right->parent = avlnode;
539 child->left = avlnode;
540 avlnode->parent = child;
541 *superparent = child;
542 child->parent = parent;
543 #ifdef AVL_COUNT
544 avlnode->count = CALC_COUNT(avlnode);
545 child->count = CALC_COUNT(child);
546 #endif
547 #ifdef AVL_DEPTH
548 avlnode->depth = CALC_DEPTH(avlnode);
549 child->depth = CALC_DEPTH(child);
550 #endif
551 } else {
552 gchild = child->left;
553 avlnode->right = gchild->left;
554 if(avlnode->right)
555 avlnode->right->parent = avlnode;
556 child->left = gchild->right;
557 if(child->left)
558 child->left->parent = child;
559 gchild->left = avlnode;
560 if(gchild->left)
561 gchild->left->parent = gchild;
562 gchild->right = child;
563 if(gchild->right)
564 gchild->right->parent = gchild;
565 *superparent = gchild;
566 gchild->parent = parent;
567 #ifdef AVL_COUNT
568 avlnode->count = CALC_COUNT(avlnode);
569 child->count = CALC_COUNT(child);
570 gchild->count = CALC_COUNT(gchild);
571 #endif
572 #ifdef AVL_DEPTH
573 avlnode->depth = CALC_DEPTH(avlnode);
574 child->depth = CALC_DEPTH(child);
575 gchild->depth = CALC_DEPTH(gchild);
576 #endif
577 }
578 break;
579 default:
580 #ifdef AVL_COUNT
581 avlnode->count = CALC_COUNT(avlnode);
582 #endif
583 #ifdef AVL_DEPTH
584 avlnode->depth = CALC_DEPTH(avlnode);
585 #endif
586 }
587 avlnode = parent;
588 }
589}
avl_node_t * avl_insert_after(avl_tree_t *avltree, avl_node_t *node, avl_node_t *newnode)
Definition: avl.cpp:274
avl_node_t * avl_insert_before(avl_tree_t *avltree, avl_node_t *node, avl_node_t *newnode)
Definition: avl.cpp:248
void avl_free_tree(avl_tree_t *avltree)
Definition: avl.cpp:218
int avl_search_closest(const avl_tree_t *avltree, const void *item, avl_node_t **avlnode)
Definition: avl.cpp:134
void avl_unlink_node(avl_tree_t *avltree, avl_node_t *avlnode)
Definition: avl.cpp:340
#define L_DEPTH(n)
Definition: avl.cpp:46
#define CALC_DEPTH(n)
Definition: avl.cpp:48
avl_node_t * avl_fixup_node(avl_tree_t *avltree, avl_node_t *newnode)
Definition: avl.cpp:410
avl_node_t * avl_init_node(avl_node_t *newnode, void *item)
Definition: avl.cpp:233
#define NODE_COUNT(n)
Definition: avl.cpp:38
#define R_DEPTH(n)
Definition: avl.cpp:47
avl_node_t * avl_insert(avl_tree_t *avltree, void *item)
Definition: avl.cpp:321
unsigned int avl_index(const avl_node_t *avlnode)
Definition: avl.cpp:118
avl_node_t * avl_at(const avl_tree_t *avltree, unsigned int index)
Definition: avl.cpp:97
avl_node_t * avl_search(const avl_tree_t *avltree, const void *item)
Definition: avl.cpp:173
void * avl_delete(avl_tree_t *avltree, const void *item)
Definition: avl.cpp:406
void * avl_delete_node(avl_tree_t *avltree, avl_node_t *avlnode)
Definition: avl.cpp:394
avl_node_t * avl_insert_node(avl_tree_t *avltree, avl_node_t *newnode)
Definition: avl.cpp:300
avl_node_t * avl_insert_top(avl_tree_t *avltree, avl_node_t *newnode)
Definition: avl.cpp:241
unsigned int avl_count(const avl_tree_t *avltree)
Definition: avl.cpp:93
avl_tree_t * avl_init_tree(avl_tree_t *rc, avl_compare_t cmp, avl_freeitem_t freeitem)
Definition: avl.cpp:178
#define R_COUNT(n)
Definition: avl.cpp:40
avl_tree_t * avl_alloc_tree(avl_compare_t cmp, avl_freeitem_t freeitem)
Definition: avl.cpp:189
void avl_clear_tree(avl_tree_t *avltree)
Definition: avl.cpp:193
void avl_free_nodes(avl_tree_t *avltree)
Definition: avl.cpp:197
#define CALC_COUNT(n)
Definition: avl.cpp:41
#define L_COUNT(n)
Definition: avl.cpp:39
void(* avl_freeitem_t)(void *)
Definition: avl.h:50
int(* avl_compare_t)(const void *, const void *)
Definition: avl.h:45
constexpr double c
The velocity of light in m/s.
Definition: Physics.h:45
Definition: avl.h:52
struct avl_node_t * left
Definition: avl.h:56
struct avl_node_t * parent
Definition: avl.h:55
struct avl_node_t * prev
Definition: avl.h:54
struct avl_node_t * next
Definition: avl.h:53
struct avl_node_t * right
Definition: avl.h:57
unsigned int count
Definition: avl.h:60
void * item
Definition: avl.h:58
unsigned char depth
Definition: avl.h:63
Definition: avl.h:67
avl_node_t * tail
Definition: avl.h:69
avl_node_t * top
Definition: avl.h:70
avl_compare_t cmp
Definition: avl.h:71
avl_freeitem_t freeitem
Definition: avl.h:72
avl_node_t * head
Definition: avl.h:68