GRASS 8 Programmer's Manual 8.6.0dev(2026)-5f4f7ad06c
Loading...
Searching...
No Matches
avl.c
Go to the documentation of this file.
1/* Produced by texiweb from libavl.w. */
2
3/* libavl - library for manipulation of binary trees.
4 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004 Free Software
5 Foundation, Inc.
6
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 3 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 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public
18 License along with this library; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 02110-1301 USA.
21 */
22
23/* Nov 2016, Markus Metz
24 * from libavl-2.0.3
25 * added safety checks and speed optimizations
26 */
27
28#include <assert.h>
29#include <stdio.h>
30#include <stdlib.h>
31#include <string.h>
32#include "avl.h"
33
34/* Creates and returns a new table
35 with comparison function |compare| using parameter |param|
36 and memory allocator |allocator|.
37 Returns |NULL| if memory allocation failed. */
38struct avl_table *avl_create(avl_comparison_func *compare, void *param,
40{
41 struct avl_table *tree;
42
44
45 if (allocator == NULL)
47
48 tree = allocator->libavl_malloc(allocator, sizeof *tree);
49 if (tree == NULL)
50 return NULL;
51
52 tree->avl_root = NULL;
53 tree->avl_compare = compare;
54 tree->avl_param = param;
55 tree->avl_alloc = allocator;
56 tree->avl_count = 0;
57 tree->avl_generation = 0;
58
59 return tree;
60}
61
62/* Search |tree| for an item matching |item|, and return it if found.
63 Otherwise return |NULL|. */
64void *avl_find(const struct avl_table *tree, const void *item)
65{
66 const struct avl_node *p;
67
68 assert(tree != NULL && item != NULL);
69
70 p = tree->avl_root;
71 while (p != NULL) {
72 int cmp = tree->avl_compare(item, p->avl_data, tree->avl_param);
73
74 if (cmp == 0)
75 return p->avl_data;
76
77 p = p->avl_link[cmp > 0];
78 }
79
80 return NULL;
81}
82
83/* Inserts |item| into |tree| and returns a pointer to |item|'s address.
84 If a duplicate item is found in the tree,
85 returns a pointer to the duplicate without inserting |item|.
86 Returns |NULL| in case of memory allocation failure. */
87void **avl_probe(struct avl_table *tree, void *item)
88{
89 struct avl_node *y, *z; /* Top node to update balance factor, and parent. */
90 struct avl_node *p, *q; /* Iterator, and parent. */
91 struct avl_node *n; /* Newly inserted node. */
92 struct avl_node *w; /* New root of rebalanced subtree. */
93 int dir; /* Direction to descend. */
94
95 unsigned char da[AVL_MAX_HEIGHT]; /* Cached comparison results. */
96 int k = 0; /* Number of cached results. */
97
98 assert(tree != NULL && item != NULL);
99
100 z = (struct avl_node *)&tree->avl_root;
101 y = tree->avl_root;
102 dir = 0;
103 q = z, p = y;
104 while (p != NULL) {
105 int cmp = tree->avl_compare(item, p->avl_data, tree->avl_param);
106
107 if (cmp == 0)
108 return &p->avl_data;
109
110 if (p->avl_balance != 0)
111 z = q, y = p, k = 0;
112 da[k++] = dir = cmp > 0;
113 q = p, p = p->avl_link[dir];
114 }
115
116 n = tree->avl_alloc->libavl_malloc(tree->avl_alloc, sizeof *n);
117 if (n == NULL)
118 return NULL;
119
120 tree->avl_count++;
121 tree->avl_generation++;
122 n->avl_link[0] = n->avl_link[1] = NULL;
123 n->avl_data = item;
124 n->avl_balance = 0;
125 if (y == NULL) {
126 tree->avl_root = n;
127
128 return &n->avl_data;
129 }
130 q->avl_link[dir] = n;
131
132 p = y, k = 0;
133 while (p != n) {
134 if (da[k] == 0)
135 p->avl_balance--;
136 else
137 p->avl_balance++;
138 p = p->avl_link[da[k]], k++;
139 }
140
141 if (y->avl_balance == -2) {
142 struct avl_node *x = y->avl_link[0];
143
144 if (x->avl_balance == -1) {
145 w = x;
146 y->avl_link[0] = x->avl_link[1];
147 x->avl_link[1] = y;
148 x->avl_balance = y->avl_balance = 0;
149 }
150 else {
151 assert(x->avl_balance == +1);
152 w = x->avl_link[1];
153 x->avl_link[1] = w->avl_link[0];
154 w->avl_link[0] = x;
155 y->avl_link[0] = w->avl_link[1];
156 w->avl_link[1] = y;
157 if (w->avl_balance == -1)
158 x->avl_balance = 0, y->avl_balance = +1;
159 else if (w->avl_balance == 0)
160 x->avl_balance = y->avl_balance = 0;
161 else /* |w->avl_balance == +1| */
162 x->avl_balance = -1, y->avl_balance = 0;
163 w->avl_balance = 0;
164 }
165 }
166 else if (y->avl_balance == +2) {
167 struct avl_node *x = y->avl_link[1];
168
169 if (x->avl_balance == +1) {
170 w = x;
171 y->avl_link[1] = x->avl_link[0];
172 x->avl_link[0] = y;
173 x->avl_balance = y->avl_balance = 0;
174 }
175 else {
176 assert(x->avl_balance == -1);
177 w = x->avl_link[0];
178 x->avl_link[0] = w->avl_link[1];
179 w->avl_link[1] = x;
180 y->avl_link[1] = w->avl_link[0];
181 w->avl_link[0] = y;
182 if (w->avl_balance == +1)
183 x->avl_balance = 0, y->avl_balance = -1;
184 else if (w->avl_balance == 0)
185 x->avl_balance = y->avl_balance = 0;
186 else /* |w->avl_balance == -1| */
187 x->avl_balance = +1, y->avl_balance = 0;
188 w->avl_balance = 0;
189 }
190 }
191 else
192 return &n->avl_data;
193 z->avl_link[y != z->avl_link[0]] = w;
194
195 return &n->avl_data;
196}
197
198/* Inserts |item| into |table|.
199 Returns |NULL| if |item| was successfully inserted
200 or if a memory allocation error occurred.
201 Otherwise, returns the duplicate item. */
202void *avl_insert(struct avl_table *table, void *item)
203{
204 void **p = avl_probe(table, item);
205
206 return p == NULL || *p == item ? NULL : *p;
207}
208
209/* Inserts |item| into |table|, replacing any duplicate item.
210 Returns |NULL| if |item| was inserted without replacing a duplicate,
211 or if a memory allocation error occurred.
212 Otherwise, returns the item that was replaced. */
213void *avl_replace(struct avl_table *table, void *item)
214{
215 void **p = avl_probe(table, item);
216
217 if (p == NULL || *p == item)
218 return NULL;
219 else {
220 void *r = *p;
221
222 *p = item;
223
224 return r;
225 }
226}
227
228/* Deletes from |tree| and returns an item matching |item|.
229 Returns a null pointer if no matching item found. */
230void *avl_delete(struct avl_table *tree, const void *item)
231{
232 /* Stack of nodes. */
233 struct avl_node *pa[AVL_MAX_HEIGHT]; /* Nodes. */
234 unsigned char da[AVL_MAX_HEIGHT]; /* |avl_link[]| indexes. */
235 int k; /* Stack pointer. */
236
237 struct avl_node *p; /* Traverses tree to find node to delete. */
238 int dir; /* Side of |pa[k]| on which |p| is linked. */
239 int cmp; /* Result of comparison between |item| and |p|. */
240
241 assert(tree != NULL && item != NULL);
242
243 pa[0] = (struct avl_node *)&tree->avl_root;
244 da[0] = 0;
245 k = 1;
246 p = tree->avl_root;
247 while (p != NULL) {
248 cmp = tree->avl_compare(item, p->avl_data, tree->avl_param);
249
250 if (cmp == 0)
251 break;
252
253 dir = cmp > 0;
254
255 pa[k] = p;
256 da[k++] = dir;
257
258 p = p->avl_link[dir];
259 }
260 if (p == NULL)
261 return NULL;
262
263 item = p->avl_data;
264
265 if (p->avl_link[1] == NULL)
266 pa[k - 1]->avl_link[da[k - 1]] = p->avl_link[0];
267 else {
268 struct avl_node *r = p->avl_link[1];
269
270 if (r->avl_link[0] == NULL) {
271 r->avl_link[0] = p->avl_link[0];
272 r->avl_balance = p->avl_balance;
273 pa[k - 1]->avl_link[da[k - 1]] = r;
274 da[k] = 1;
275 pa[k++] = r;
276 }
277 else {
278 struct avl_node *s;
279 int j = k++;
280
281 while (r != NULL) {
282 da[k] = 0;
283 pa[k++] = r;
284 s = r->avl_link[0];
285 if (s->avl_link[0] == NULL)
286 break;
287
288 r = s;
289 }
290
291 s->avl_link[0] = p->avl_link[0];
292 r->avl_link[0] = s->avl_link[1];
293 s->avl_link[1] = p->avl_link[1];
294 s->avl_balance = p->avl_balance;
295
296 pa[j - 1]->avl_link[da[j - 1]] = s;
297 da[j] = 1;
298 pa[j] = s;
299 }
300 }
301
302 tree->avl_alloc->libavl_free(tree->avl_alloc, p);
303
304 assert(k > 0);
305 while (--k > 0) {
306 struct avl_node *y = pa[k];
307
308 if (da[k] == 0) {
309 y->avl_balance++;
310 if (y->avl_balance == +1)
311 break;
312 else if (y->avl_balance == +2) {
313 struct avl_node *x = y->avl_link[1];
314
315 if (x->avl_balance == -1) {
316 struct avl_node *w;
317
318 assert(x->avl_balance == -1);
319 w = x->avl_link[0];
320 x->avl_link[0] = w->avl_link[1];
321 w->avl_link[1] = x;
322 y->avl_link[1] = w->avl_link[0];
323 w->avl_link[0] = y;
324 if (w->avl_balance == +1)
325 x->avl_balance = 0, y->avl_balance = -1;
326 else if (w->avl_balance == 0)
327 x->avl_balance = y->avl_balance = 0;
328 else /* |w->avl_balance == -1| */
329 x->avl_balance = +1, y->avl_balance = 0;
330 w->avl_balance = 0;
331 pa[k - 1]->avl_link[da[k - 1]] = w;
332 }
333 else {
334 y->avl_link[1] = x->avl_link[0];
335 x->avl_link[0] = y;
336 pa[k - 1]->avl_link[da[k - 1]] = x;
337 if (x->avl_balance == 0) {
338 x->avl_balance = -1;
339 y->avl_balance = +1;
340 break;
341 }
342 else
343 x->avl_balance = y->avl_balance = 0;
344 }
345 }
346 }
347 else {
348 y->avl_balance--;
349 if (y->avl_balance == -1)
350 break;
351 else if (y->avl_balance == -2) {
352 struct avl_node *x = y->avl_link[0];
353
354 if (x->avl_balance == +1) {
355 struct avl_node *w;
356
357 assert(x->avl_balance == +1);
358 w = x->avl_link[1];
359 x->avl_link[1] = w->avl_link[0];
360 w->avl_link[0] = x;
361 y->avl_link[0] = w->avl_link[1];
362 w->avl_link[1] = y;
363 if (w->avl_balance == -1)
364 x->avl_balance = 0, y->avl_balance = +1;
365 else if (w->avl_balance == 0)
366 x->avl_balance = y->avl_balance = 0;
367 else /* |w->avl_balance == +1| */
368 x->avl_balance = -1, y->avl_balance = 0;
369 w->avl_balance = 0;
370 pa[k - 1]->avl_link[da[k - 1]] = w;
371 }
372 else {
373 y->avl_link[0] = x->avl_link[1];
374 x->avl_link[1] = y;
375 pa[k - 1]->avl_link[da[k - 1]] = x;
376 if (x->avl_balance == 0) {
377 x->avl_balance = +1;
378 y->avl_balance = -1;
379 break;
380 }
381 else
382 x->avl_balance = y->avl_balance = 0;
383 }
384 }
385 }
386 }
387
388 tree->avl_count--;
389 tree->avl_generation++;
390
391 return (void *)item;
392}
393
394/* Refreshes the stack of parent pointers in |trav|
395 and updates its generation number. */
396static void trav_refresh(struct avl_traverser *trav)
397{
398 assert(trav != NULL);
399
400 trav->avl_generation = trav->avl_table->avl_generation;
401
402 if (trav->avl_node != NULL) {
403 avl_comparison_func *cmp = trav->avl_table->avl_compare;
404 void *param = trav->avl_table->avl_param;
405 struct avl_node *node = trav->avl_node;
406 struct avl_node *i;
407
408 trav->avl_height = 0;
409 for (i = trav->avl_table->avl_root; i != node;) {
410 assert(trav->avl_height < AVL_MAX_HEIGHT);
411 assert(i != NULL);
412
413 trav->avl_stack[trav->avl_height++] = i;
414 i = i->avl_link[cmp(node->avl_data, i->avl_data, param) > 0];
415 }
416 }
417}
418
419/* Initializes |trav| for use with |tree|
420 and selects the null node. */
421void avl_t_init(struct avl_traverser *trav, struct avl_table *tree)
422{
423 trav->avl_table = tree;
424 trav->avl_node = NULL;
425 trav->avl_height = 0;
426 trav->avl_generation = tree->avl_generation;
427}
428
429/* Initializes |trav| for |tree|
430 and selects and returns a pointer to its least-valued item.
431 Returns |NULL| if |tree| contains no nodes. */
432void *avl_t_first(struct avl_traverser *trav, struct avl_table *tree)
433{
434 struct avl_node *x;
435
436 assert(tree != NULL && trav != NULL);
437
438 trav->avl_table = tree;
439 trav->avl_height = 0;
440 trav->avl_generation = tree->avl_generation;
441
442 x = tree->avl_root;
443 if (x != NULL)
444 while (x->avl_link[0] != NULL) {
445 assert(trav->avl_height < AVL_MAX_HEIGHT);
446 trav->avl_stack[trav->avl_height++] = x;
447 x = x->avl_link[0];
448 }
449 trav->avl_node = x;
450
451 return x != NULL ? x->avl_data : NULL;
452}
453
454/* Initializes |trav| for |tree|
455 and selects and returns a pointer to its greatest-valued item.
456 Returns |NULL| if |tree| contains no nodes. */
457void *avl_t_last(struct avl_traverser *trav, struct avl_table *tree)
458{
459 struct avl_node *x;
460
461 assert(tree != NULL && trav != NULL);
462
463 trav->avl_table = tree;
464 trav->avl_height = 0;
465 trav->avl_generation = tree->avl_generation;
466
467 x = tree->avl_root;
468 if (x != NULL)
469 while (x->avl_link[1] != NULL) {
470 assert(trav->avl_height < AVL_MAX_HEIGHT);
471 trav->avl_stack[trav->avl_height++] = x;
472 x = x->avl_link[1];
473 }
474 trav->avl_node = x;
475
476 return x != NULL ? x->avl_data : NULL;
477}
478
479/* Searches for |item| in |tree|.
480 If found, initializes |trav| to the item found and returns the item
481 as well.
482 If there is no matching item, initializes |trav| to the null item
483 and returns |NULL|. */
484void *avl_t_find(struct avl_traverser *trav, struct avl_table *tree, void *item)
485{
486 struct avl_node *p;
487
488 assert(trav != NULL && tree != NULL && item != NULL);
489 trav->avl_table = tree;
490 trav->avl_height = 0;
491 trav->avl_generation = tree->avl_generation;
492 p = tree->avl_root;
493 while (p != NULL) {
494 int cmp = tree->avl_compare(item, p->avl_data, tree->avl_param);
495
496 if (cmp == 0) {
497 trav->avl_node = p;
498
499 return p->avl_data;
500 }
501
502 assert(trav->avl_height < AVL_MAX_HEIGHT);
503 trav->avl_stack[trav->avl_height++] = p;
504 p = p->avl_link[cmp > 0];
505 }
506
507 trav->avl_height = 0;
508 trav->avl_node = NULL;
509
510 return NULL;
511}
512
513/* Attempts to insert |item| into |tree|.
514 If |item| is inserted successfully, it is returned and |trav| is
515 initialized to its location.
516 If a duplicate is found, it is returned and |trav| is initialized to
517 its location. No replacement of the item occurs.
518 If a memory allocation failure occurs, |NULL| is returned and |trav|
519 is initialized to the null item. */
520void *avl_t_insert(struct avl_traverser *trav, struct avl_table *tree,
521 void *item)
522{
523 void **p;
524
525 assert(trav != NULL && tree != NULL && item != NULL);
526
527 p = avl_probe(tree, item);
528 if (p != NULL) {
529 trav->avl_table = tree;
530 trav->avl_node =
531 ((struct avl_node *)((char *)p -
532 offsetof(struct avl_node, avl_data)));
533
534 trav->avl_generation = tree->avl_generation - 1;
535
536 return *p;
537 }
538 else {
539 avl_t_init(trav, tree);
540
541 return NULL;
542 }
543}
544
545/* Initializes |trav| to have the same current node as |src|. */
546void *avl_t_copy(struct avl_traverser *trav, const struct avl_traverser *src)
547{
548 assert(trav != NULL && src != NULL);
549
550 if (trav != src) {
551 trav->avl_table = src->avl_table;
552 trav->avl_node = src->avl_node;
553 trav->avl_generation = src->avl_generation;
554 if (trav->avl_generation == trav->avl_table->avl_generation) {
555 trav->avl_height = src->avl_height;
556 memcpy(trav->avl_stack, (const void *)src->avl_stack,
557 sizeof *trav->avl_stack * trav->avl_height);
558 }
559 }
560
561 return trav->avl_node != NULL ? trav->avl_node->avl_data : NULL;
562}
563
564/* Returns the next data item in inorder
565 within the tree being traversed with |trav|,
566 or if there are no more data items returns |NULL|. */
568{
569 struct avl_node *x;
570
571 assert(trav != NULL);
572
573 if (trav->avl_generation != trav->avl_table->avl_generation)
574 trav_refresh(trav);
575
576 x = trav->avl_node;
577 if (x == NULL) {
578 return avl_t_first(trav, trav->avl_table);
579 }
580 else if (x->avl_link[1] != NULL) {
581 assert(trav->avl_height < AVL_MAX_HEIGHT);
582 trav->avl_stack[trav->avl_height++] = x;
583 x = x->avl_link[1];
584
585 while (x->avl_link[0] != NULL) {
586 assert(trav->avl_height < AVL_MAX_HEIGHT);
587 trav->avl_stack[trav->avl_height++] = x;
588 x = x->avl_link[0];
589 }
590 }
591 else {
592 struct avl_node *y;
593
594 do {
595 if (trav->avl_height == 0) {
596 trav->avl_node = NULL;
597 return NULL;
598 }
599
600 y = x;
601 x = trav->avl_stack[--trav->avl_height];
602 } while (y == x->avl_link[1]);
603 }
604 trav->avl_node = x;
605
606 return x->avl_data;
607}
608
609/* Returns the previous data item in inorder
610 within the tree being traversed with |trav|,
611 or if there are no more data items returns |NULL|. */
613{
614 struct avl_node *x;
615
616 assert(trav != NULL);
617
618 if (trav->avl_generation != trav->avl_table->avl_generation)
619 trav_refresh(trav);
620
621 x = trav->avl_node;
622 if (x == NULL) {
623 return avl_t_last(trav, trav->avl_table);
624 }
625 else if (x->avl_link[0] != NULL) {
626 assert(trav->avl_height < AVL_MAX_HEIGHT);
627 trav->avl_stack[trav->avl_height++] = x;
628 x = x->avl_link[0];
629
630 while (x->avl_link[1] != NULL) {
631 assert(trav->avl_height < AVL_MAX_HEIGHT);
632 trav->avl_stack[trav->avl_height++] = x;
633 x = x->avl_link[1];
634 }
635 }
636 else {
637 struct avl_node *y;
638
639 do {
640 if (trav->avl_height == 0) {
641 trav->avl_node = NULL;
642 return NULL;
643 }
644
645 y = x;
646 x = trav->avl_stack[--trav->avl_height];
647 } while (y == x->avl_link[0]);
648 }
649 trav->avl_node = x;
650
651 return x->avl_data;
652}
653
654/* Returns |trav|'s current item. */
656{
657 assert(trav != NULL);
658
659 return trav->avl_node != NULL ? trav->avl_node->avl_data : NULL;
660}
661
662/* Replaces the current item in |trav| by |new| and returns the item replaced.
663 |trav| must not have the null item selected.
664 The new item must not upset the ordering of the tree. */
665void *avl_t_replace(struct avl_traverser *trav, void *new)
666{
667 void *old;
668
669 assert(trav != NULL && trav->avl_node != NULL && new != NULL);
670 old = trav->avl_node->avl_data;
671 trav->avl_node->avl_data = new;
672
673 return old;
674}
675
676/* Destroys |new| with |avl_destroy (new, destroy)|,
677 first setting right links of nodes in |stack| within |new|
678 to null pointers to avoid touching uninitialized data. */
679static void copy_error_recovery(struct avl_node **stack, int height,
680 struct avl_table *new, avl_item_func *destroy)
681{
682 assert(stack != NULL && height >= 0 && new != NULL);
683
684 for (; height > 2; height -= 2)
685 stack[height - 1]->avl_link[1] = NULL;
686 avl_destroy(new, destroy);
687}
688
689/* Copies |org| to a newly created tree, which is returned.
690 If |copy != NULL|, each data item in |org| is first passed to |copy|,
691 and the return values are inserted into the tree,
692 with |NULL| return values taken as indications of failure.
693 On failure, destroys the partially created new tree,
694 applying |destroy|, if non-null, to each item in the new tree so far,
695 and returns |NULL|.
696 If |allocator != NULL|, it is used for allocation in the new tree.
697 Otherwise, the same allocator used for |org| is used. */
701{
702 struct avl_node *stack[2 * (AVL_MAX_HEIGHT + 1)];
703 int height = 0;
704
705 struct avl_table *new;
706 const struct avl_node *x;
707 struct avl_node *y;
708
709 assert(org != NULL);
710 new = avl_create(org->avl_compare, org->avl_param,
711 allocator != NULL ? allocator : org->avl_alloc);
712 if (new == NULL)
713 return NULL;
714
715 new->avl_count = org->avl_count;
716 if (new->avl_count == 0)
717 return new;
718
719 x = (const struct avl_node *)&org->avl_root;
720 y = (struct avl_node *)&new->avl_root;
721 while (x != NULL) {
722 while (x->avl_link[0] != NULL) {
723 assert(height < 2 * (AVL_MAX_HEIGHT + 1));
724
725 y->avl_link[0] = new->avl_alloc->libavl_malloc(
726 new->avl_alloc, sizeof *y->avl_link[0]);
727 if (y->avl_link[0] == NULL) {
728 if (y != (struct avl_node *)&new->avl_root) {
729 y->avl_data = NULL;
730 y->avl_link[1] = NULL;
731 }
732
733 copy_error_recovery(stack, height, new, destroy);
734 return NULL;
735 }
736
737 stack[height++] = (struct avl_node *)x;
738 stack[height++] = y;
739 x = x->avl_link[0];
740 y = y->avl_link[0];
741 }
742 y->avl_link[0] = NULL;
743
744 for (;;) {
745 y->avl_balance = x->avl_balance;
746 if (copy == NULL)
747 y->avl_data = x->avl_data;
748 else {
749 y->avl_data = copy(x->avl_data, org->avl_param);
750 if (y->avl_data == NULL) {
751 y->avl_link[1] = NULL;
752 copy_error_recovery(stack, height, new, destroy);
753 return NULL;
754 }
755 }
756
757 if (x->avl_link[1] != NULL) {
758 y->avl_link[1] = new->avl_alloc->libavl_malloc(
759 new->avl_alloc, sizeof *y->avl_link[1]);
760 if (y->avl_link[1] == NULL) {
761 copy_error_recovery(stack, height, new, destroy);
762 return NULL;
763 }
764
765 x = x->avl_link[1];
766 y = y->avl_link[1];
767 break;
768 }
769 else
770 y->avl_link[1] = NULL;
771
772 if (height <= 2)
773 return new;
774
775 y = stack[--height];
776 x = stack[--height];
777 }
778 }
779
780 return new;
781}
782
783/* Frees storage allocated for |tree|.
784 If |destroy != NULL|, applies it to each data item in inorder. */
786{
787 struct avl_node *p, *q;
788
789 assert(tree != NULL);
790
791 p = tree->avl_root;
792 while (p != NULL) {
793 if (p->avl_link[0] == NULL) {
794 q = p->avl_link[1];
795 if (destroy != NULL && p->avl_data != NULL)
796 destroy(p->avl_data, tree->avl_param);
797 tree->avl_alloc->libavl_free(tree->avl_alloc, p);
798 }
799 else {
800 q = p->avl_link[0];
801 p->avl_link[0] = q->avl_link[1];
802 q->avl_link[1] = p;
803 }
804 p = q;
805 }
806
807 tree->avl_alloc->libavl_free(tree->avl_alloc, tree);
808}
809
810/* Allocates |size| bytes of space using |malloc()|.
811 Returns a null pointer if allocation fails. */
812void *avl_malloc(struct libavl_allocator *allocator, size_t size)
813{
814 assert(allocator != NULL && size > 0);
815
816 return malloc(size);
817}
818
819/* Frees |block|. */
820void avl_free(struct libavl_allocator *allocator, void *block)
821{
822 assert(allocator != NULL && block != NULL);
823 free(block);
824}
825
826/* Default memory allocator that uses |malloc()| and |free()|. */
828
829#undef NDEBUG
830#include <assert.h>
831
832/* Asserts that |avl_insert()| succeeds at inserting |item| into |table|. */
833void(avl_assert_insert)(struct avl_table *table, void *item)
834{
835 void **p = avl_probe(table, item);
836
837 assert(p != NULL && *p == item);
838}
839
840/* Asserts that |avl_delete()| really removes |item| from |table|,
841 and returns the removed item. */
842void *(avl_assert_delete)(struct avl_table * table, void *item)
843{
844 void *p = avl_delete(table, item);
845
846 assert(p != NULL);
847
848 return p;
849}
struct libavl_allocator avl_allocator_default
Definition avl.c:827
void avl_free(struct libavl_allocator *allocator, void *block)
Definition avl.c:820
void * avl_malloc(struct libavl_allocator *allocator, size_t size)
Definition avl.c:812
void * avl_copy_func(void *avl_item, void *avl_param)
Definition avl.h:32
#define AVL_MAX_HEIGHT
Definition avl.h:50
void avl_item_func(void *avl_item, void *avl_param)
Definition avl.h:31
int avl_comparison_func(const void *avl_a, const void *avl_b, void *avl_param)
Definition avl.h:29
#define NULL
Definition ccmath.h:32
int compare(const void *a, const void *b)
Definition dgraph.c:168
#define assert(condition)
Definition lz4.c:291
double r
Definition r_raster.c:39
void * malloc(unsigned)
void free(void *)
Definition avl.h:64
void * avl_data
Definition avl.h:66
struct avl_node * avl_link[2]
Definition avl.h:65
signed char avl_balance
Definition avl.h:67
avl_comparison_func * avl_compare
Definition avl.h:56
void * avl_param
Definition avl.h:57
size_t avl_count
Definition avl.h:59
struct libavl_allocator * avl_alloc
Definition avl.h:58
unsigned long avl_generation
Definition avl.h:60
struct avl_node * avl_root
Definition avl.h:55
unsigned long avl_generation
Definition avl.h:77
struct avl_table * avl_table
Definition avl.h:72
struct avl_node * avl_stack[92]
Definition avl.h:74
struct avl_node * avl_node
Definition avl.h:73
size_t avl_height
Definition avl.h:76
#define avl_find
Definition tree.h:38
#define avl_probe
Definition tree.h:34
#define avl_copy
Definition tree.h:32
#define avl_t_replace
Definition tree.h:50
#define avl_create
Definition tree.h:31
#define avl_t_cur
Definition tree.h:49
#define avl_t_insert
Definition tree.h:45
#define avl_t_next
Definition tree.h:47
#define avl_t_prev
Definition tree.h:48
#define avl_t_find
Definition tree.h:44
#define avl_assert_insert
Definition tree.h:39
#define avl_replace
Definition tree.h:36
#define avl_assert_delete
Definition tree.h:40
#define avl_insert
Definition tree.h:35
#define avl_t_first
Definition tree.h:42
#define avl_t_last
Definition tree.h:43
#define avl_destroy
Definition tree.h:33
#define avl_t_copy
Definition tree.h:46
#define avl_t_init
Definition tree.h:41
#define avl_delete
Definition tree.h:37
#define x