1 /* Produced by texiweb from libavl.w. */
3 /* libavl - library for manipulation of binary trees.
4 Copyright (C) 1998-2002, 2004 Free Software Foundation, Inc.
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License as
8 published by the Free Software Foundation; either version 2 of the
9 License, or (at your option) any later version.
11 This program is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 See the GNU General Public License for more details.
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., 59 Temple Place - Suite 330, Boston, MA
21 The author may be contacted at <blp@gnu.org> on the Internet, or
22 write to Ben Pfaff, Stanford University, Computer Science Dept., 353
23 Serra Mall, Stanford CA 94305, USA.
31 /* Creates and returns a new table
32 with comparison function |compare| using parameter |param|
33 and memory allocator |allocator|.
34 Returns |NULL| if memory allocation failed. */
36 prb_create (prb_comparison_func
*compare
, void *param
,
37 struct libavl_allocator
*allocator
)
39 struct prb_table
*tree
;
41 assert (compare
!= NULL
);
43 if (allocator
== NULL
)
44 allocator
= &prb_allocator_default
;
46 tree
= allocator
->libavl_malloc (allocator
, sizeof *tree
);
50 tree
->prb_root
= NULL
;
51 tree
->prb_compare
= compare
;
52 tree
->prb_param
= param
;
53 tree
->prb_alloc
= allocator
;
59 /* Search |tree| for an item matching |item|, and return it if found.
60 Otherwise return |NULL|. */
62 prb_find (const struct prb_table
*tree
, const void *item
)
64 const struct prb_node
*p
;
66 assert (tree
!= NULL
&& item
!= NULL
);
67 for (p
= tree
->prb_root
; p
!= NULL
; )
69 int cmp
= tree
->prb_compare (item
, p
->prb_data
, tree
->prb_param
);
82 /* Inserts |item| into |tree| and returns a pointer to |item|'s address.
83 If a duplicate item is found in the tree,
84 returns a pointer to the duplicate without inserting |item|.
85 Returns |NULL| in case of memory allocation failure. */
87 prb_probe (struct prb_table
*tree
, void *item
)
89 struct prb_node
*p
; /* Traverses tree looking for insertion point. */
90 struct prb_node
*q
; /* Parent of |p|; node at which we are rebalancing. */
91 struct prb_node
*n
; /* Newly inserted node. */
92 int dir
; /* Side of |q| on which |n| is inserted. */
94 assert (tree
!= NULL
&& item
!= NULL
);
96 for (q
= NULL
, p
= tree
->prb_root
; p
!= NULL
; q
= p
, p
= p
->prb_link
[dir
])
98 int cmp
= tree
->prb_compare (item
, p
->prb_data
, tree
->prb_param
);
104 n
= tree
->prb_alloc
->libavl_malloc (tree
->prb_alloc
, sizeof *p
);
109 n
->prb_link
[0] = n
->prb_link
[1] = NULL
;
113 q
->prb_link
[dir
] = n
;
116 n
->prb_color
= PRB_RED
;
121 struct prb_node
*f
; /* Parent of |q|. */
122 struct prb_node
*g
; /* Grandparent of |q|. */
125 if (f
== NULL
|| f
->prb_color
== PRB_BLACK
)
132 if (g
->prb_link
[0] == f
)
134 struct prb_node
*y
= g
->prb_link
[1];
135 if (y
!= NULL
&& y
->prb_color
== PRB_RED
)
137 f
->prb_color
= y
->prb_color
= PRB_BLACK
;
138 g
->prb_color
= PRB_RED
;
143 struct prb_node
*h
; /* Great-grandparent of |q|. */
147 h
= (struct prb_node
*) &tree
->prb_root
;
149 if (f
->prb_link
[1] == q
)
151 f
->prb_link
[1] = q
->prb_link
[0];
155 if (f
->prb_link
[1] != NULL
)
156 f
->prb_link
[1]->prb_parent
= f
;
161 g
->prb_color
= PRB_RED
;
162 f
->prb_color
= PRB_BLACK
;
164 g
->prb_link
[0] = f
->prb_link
[1];
166 h
->prb_link
[h
->prb_link
[0] != g
] = f
;
168 f
->prb_parent
= g
->prb_parent
;
170 if (g
->prb_link
[0] != NULL
)
171 g
->prb_link
[0]->prb_parent
= g
;
177 struct prb_node
*y
= g
->prb_link
[0];
178 if (y
!= NULL
&& y
->prb_color
== PRB_RED
)
180 f
->prb_color
= y
->prb_color
= PRB_BLACK
;
181 g
->prb_color
= PRB_RED
;
186 struct prb_node
*h
; /* Great-grandparent of |q|. */
190 h
= (struct prb_node
*) &tree
->prb_root
;
192 if (f
->prb_link
[0] == q
)
194 f
->prb_link
[0] = q
->prb_link
[1];
198 if (f
->prb_link
[0] != NULL
)
199 f
->prb_link
[0]->prb_parent
= f
;
204 g
->prb_color
= PRB_RED
;
205 f
->prb_color
= PRB_BLACK
;
207 g
->prb_link
[1] = f
->prb_link
[0];
209 h
->prb_link
[h
->prb_link
[0] != g
] = f
;
211 f
->prb_parent
= g
->prb_parent
;
213 if (g
->prb_link
[1] != NULL
)
214 g
->prb_link
[1]->prb_parent
= g
;
219 tree
->prb_root
->prb_color
= PRB_BLACK
;
224 /* Inserts |item| into |table|.
225 Returns |NULL| if |item| was successfully inserted
226 or if a memory allocation error occurred.
227 Otherwise, returns the duplicate item. */
229 prb_insert (struct prb_table
*table
, void *item
)
231 void **p
= prb_probe (table
, item
);
232 return p
== NULL
|| *p
== item
? NULL
: *p
;
235 /* Inserts |item| into |table|, replacing any duplicate item.
236 Returns |NULL| if |item| was inserted without replacing a duplicate,
237 or if a memory allocation error occurred.
238 Otherwise, returns the item that was replaced. */
240 prb_replace (struct prb_table
*table
, void *item
)
242 void **p
= prb_probe (table
, item
);
243 if (p
== NULL
|| *p
== item
)
253 /* Deletes from |tree| and returns an item matching |item|.
254 Returns a null pointer if no matching item found. */
256 prb_delete (struct prb_table
*tree
, const void *item
)
258 struct prb_node
*p
; /* Node to delete. */
259 struct prb_node
*q
; /* Parent of |p|. */
260 struct prb_node
*f
; /* Node at which we are rebalancing. */
261 int dir
; /* Side of |q| on which |p| is a child;
262 side of |f| from which node was deleted. */
264 assert (tree
!= NULL
&& item
!= NULL
);
266 if (tree
->prb_root
== NULL
)
272 int cmp
= tree
->prb_compare (item
, p
->prb_data
, tree
->prb_param
);
277 p
= p
->prb_link
[dir
];
286 q
= (struct prb_node
*) &tree
->prb_root
;
290 if (p
->prb_link
[1] == NULL
)
292 q
->prb_link
[dir
] = p
->prb_link
[0];
293 if (q
->prb_link
[dir
] != NULL
)
294 q
->prb_link
[dir
]->prb_parent
= p
->prb_parent
;
301 struct prb_node
*r
= p
->prb_link
[1];
303 if (r
->prb_link
[0] == NULL
)
305 r
->prb_link
[0] = p
->prb_link
[0];
306 q
->prb_link
[dir
] = r
;
307 r
->prb_parent
= p
->prb_parent
;
308 if (r
->prb_link
[0] != NULL
)
309 r
->prb_link
[0]->prb_parent
= r
;
312 p
->prb_color
= r
->prb_color
;
320 struct prb_node
*s
= r
->prb_link
[0];
321 while (s
->prb_link
[0] != NULL
)
324 r
->prb_link
[0] = s
->prb_link
[1];
325 s
->prb_link
[0] = p
->prb_link
[0];
326 s
->prb_link
[1] = p
->prb_link
[1];
327 q
->prb_link
[dir
] = s
;
328 if (s
->prb_link
[0] != NULL
)
329 s
->prb_link
[0]->prb_parent
= s
;
330 s
->prb_link
[1]->prb_parent
= s
;
331 s
->prb_parent
= p
->prb_parent
;
332 if (r
->prb_link
[0] != NULL
)
333 r
->prb_link
[0]->prb_parent
= r
;
336 p
->prb_color
= s
->prb_color
;
344 if (p
->prb_color
== PRB_BLACK
)
348 struct prb_node
*x
; /* Node we want to recolor black if possible. */
349 struct prb_node
*g
; /* Parent of |f|. */
350 struct prb_node
*t
; /* Temporary for use in finding parent. */
352 x
= f
->prb_link
[dir
];
353 if (x
!= NULL
&& x
->prb_color
== PRB_RED
)
355 x
->prb_color
= PRB_BLACK
;
359 if (f
== (struct prb_node
*) &tree
->prb_root
)
364 g
= (struct prb_node
*) &tree
->prb_root
;
368 struct prb_node
*w
= f
->prb_link
[1];
370 if (w
->prb_color
== PRB_RED
)
372 w
->prb_color
= PRB_BLACK
;
373 f
->prb_color
= PRB_RED
;
375 f
->prb_link
[1] = w
->prb_link
[0];
377 g
->prb_link
[g
->prb_link
[0] != f
] = w
;
379 w
->prb_parent
= f
->prb_parent
;
388 if ((w
->prb_link
[0] == NULL
389 || w
->prb_link
[0]->prb_color
== PRB_BLACK
)
390 && (w
->prb_link
[1] == NULL
391 || w
->prb_link
[1]->prb_color
== PRB_BLACK
))
393 w
->prb_color
= PRB_RED
;
397 if (w
->prb_link
[1] == NULL
398 || w
->prb_link
[1]->prb_color
== PRB_BLACK
)
400 struct prb_node
*y
= w
->prb_link
[0];
401 y
->prb_color
= PRB_BLACK
;
402 w
->prb_color
= PRB_RED
;
403 w
->prb_link
[0] = y
->prb_link
[1];
405 if (w
->prb_link
[0] != NULL
)
406 w
->prb_link
[0]->prb_parent
= w
;
407 w
= f
->prb_link
[1] = y
;
408 w
->prb_link
[1]->prb_parent
= w
;
411 w
->prb_color
= f
->prb_color
;
412 f
->prb_color
= PRB_BLACK
;
413 w
->prb_link
[1]->prb_color
= PRB_BLACK
;
415 f
->prb_link
[1] = w
->prb_link
[0];
417 g
->prb_link
[g
->prb_link
[0] != f
] = w
;
419 w
->prb_parent
= f
->prb_parent
;
421 if (f
->prb_link
[1] != NULL
)
422 f
->prb_link
[1]->prb_parent
= f
;
428 struct prb_node
*w
= f
->prb_link
[0];
430 if (w
->prb_color
== PRB_RED
)
432 w
->prb_color
= PRB_BLACK
;
433 f
->prb_color
= PRB_RED
;
435 f
->prb_link
[0] = w
->prb_link
[1];
437 g
->prb_link
[g
->prb_link
[0] != f
] = w
;
439 w
->prb_parent
= f
->prb_parent
;
448 if ((w
->prb_link
[0] == NULL
449 || w
->prb_link
[0]->prb_color
== PRB_BLACK
)
450 && (w
->prb_link
[1] == NULL
451 || w
->prb_link
[1]->prb_color
== PRB_BLACK
))
453 w
->prb_color
= PRB_RED
;
457 if (w
->prb_link
[0] == NULL
458 || w
->prb_link
[0]->prb_color
== PRB_BLACK
)
460 struct prb_node
*y
= w
->prb_link
[1];
461 y
->prb_color
= PRB_BLACK
;
462 w
->prb_color
= PRB_RED
;
463 w
->prb_link
[1] = y
->prb_link
[0];
465 if (w
->prb_link
[1] != NULL
)
466 w
->prb_link
[1]->prb_parent
= w
;
467 w
= f
->prb_link
[0] = y
;
468 w
->prb_link
[0]->prb_parent
= w
;
471 w
->prb_color
= f
->prb_color
;
472 f
->prb_color
= PRB_BLACK
;
473 w
->prb_link
[0]->prb_color
= PRB_BLACK
;
475 f
->prb_link
[0] = w
->prb_link
[1];
477 g
->prb_link
[g
->prb_link
[0] != f
] = w
;
479 w
->prb_parent
= f
->prb_parent
;
481 if (f
->prb_link
[0] != NULL
)
482 f
->prb_link
[0]->prb_parent
= f
;
490 f
= (struct prb_node
*) &tree
->prb_root
;
491 dir
= f
->prb_link
[0] != t
;
495 tree
->prb_alloc
->libavl_free (tree
->prb_alloc
, p
);
497 return (void *) item
;
500 /* Initializes |trav| for use with |tree|
501 and selects the null node. */
503 prb_t_init (struct prb_traverser
*trav
, struct prb_table
*tree
)
505 trav
->prb_table
= tree
;
506 trav
->prb_node
= NULL
;
509 /* Initializes |trav| for |tree|.
510 Returns data item in |tree| with the least value,
511 or |NULL| if |tree| is empty. */
513 prb_t_first (struct prb_traverser
*trav
, struct prb_table
*tree
)
515 assert (tree
!= NULL
&& trav
!= NULL
);
517 trav
->prb_table
= tree
;
518 trav
->prb_node
= tree
->prb_root
;
519 if (trav
->prb_node
!= NULL
)
521 while (trav
->prb_node
->prb_link
[0] != NULL
)
522 trav
->prb_node
= trav
->prb_node
->prb_link
[0];
523 return trav
->prb_node
->prb_data
;
529 /* Initializes |trav| for |tree|.
530 Returns data item in |tree| with the greatest value,
531 or |NULL| if |tree| is empty. */
533 prb_t_last (struct prb_traverser
*trav
, struct prb_table
*tree
)
535 assert (tree
!= NULL
&& trav
!= NULL
);
537 trav
->prb_table
= tree
;
538 trav
->prb_node
= tree
->prb_root
;
539 if (trav
->prb_node
!= NULL
)
541 while (trav
->prb_node
->prb_link
[1] != NULL
)
542 trav
->prb_node
= trav
->prb_node
->prb_link
[1];
543 return trav
->prb_node
->prb_data
;
549 /* Searches for |item| in |tree|.
550 If found, initializes |trav| to the item found and returns the item
552 If there is no matching item, initializes |trav| to the null item
553 and returns |NULL|. */
555 prb_t_find (struct prb_traverser
*trav
, struct prb_table
*tree
, void *item
)
560 assert (trav
!= NULL
&& tree
!= NULL
&& item
!= NULL
);
562 trav
->prb_table
= tree
;
563 for (p
= tree
->prb_root
; p
!= NULL
; p
= p
->prb_link
[dir
])
565 int cmp
= tree
->prb_compare (item
, p
->prb_data
, tree
->prb_param
);
575 trav
->prb_node
= NULL
;
579 /* Attempts to insert |item| into |tree|.
580 If |item| is inserted successfully, it is returned and |trav| is
581 initialized to its location.
582 If a duplicate is found, it is returned and |trav| is initialized to
583 its location. No replacement of the item occurs.
584 If a memory allocation failure occurs, |NULL| is returned and |trav|
585 is initialized to the null item. */
587 prb_t_insert (struct prb_traverser
*trav
,
588 struct prb_table
*tree
, void *item
)
592 assert (trav
!= NULL
&& tree
!= NULL
&& item
!= NULL
);
594 p
= prb_probe (tree
, item
);
597 trav
->prb_table
= tree
;
600 ((char *) p
- offsetof (struct prb_node
, prb_data
)));
605 prb_t_init (trav
, tree
);
610 /* Initializes |trav| to have the same current node as |src|. */
612 prb_t_copy (struct prb_traverser
*trav
, const struct prb_traverser
*src
)
614 assert (trav
!= NULL
&& src
!= NULL
);
616 trav
->prb_table
= src
->prb_table
;
617 trav
->prb_node
= src
->prb_node
;
619 return trav
->prb_node
!= NULL
? trav
->prb_node
->prb_data
: NULL
;
622 /* Returns the next data item in inorder
623 within the tree being traversed with |trav|,
624 or if there are no more data items returns |NULL|. */
626 prb_t_next (struct prb_traverser
*trav
)
628 assert (trav
!= NULL
);
630 if (trav
->prb_node
== NULL
)
631 return prb_t_first (trav
, trav
->prb_table
);
632 else if (trav
->prb_node
->prb_link
[1] == NULL
)
634 struct prb_node
*q
, *p
; /* Current node and its child. */
635 for (p
= trav
->prb_node
, q
= p
->prb_parent
; ;
636 p
= q
, q
= q
->prb_parent
)
637 if (q
== NULL
|| p
== q
->prb_link
[0])
640 return trav
->prb_node
!= NULL
? trav
->prb_node
->prb_data
: NULL
;
645 trav
->prb_node
= trav
->prb_node
->prb_link
[1];
646 while (trav
->prb_node
->prb_link
[0] != NULL
)
647 trav
->prb_node
= trav
->prb_node
->prb_link
[0];
648 return trav
->prb_node
->prb_data
;
652 /* Returns the previous data item in inorder
653 within the tree being traversed with |trav|,
654 or if there are no more data items returns |NULL|. */
656 prb_t_prev (struct prb_traverser
*trav
)
658 assert (trav
!= NULL
);
660 if (trav
->prb_node
== NULL
)
661 return prb_t_last (trav
, trav
->prb_table
);
662 else if (trav
->prb_node
->prb_link
[0] == NULL
)
664 struct prb_node
*q
, *p
; /* Current node and its child. */
665 for (p
= trav
->prb_node
, q
= p
->prb_parent
; ;
666 p
= q
, q
= q
->prb_parent
)
667 if (q
== NULL
|| p
== q
->prb_link
[1])
670 return trav
->prb_node
!= NULL
? trav
->prb_node
->prb_data
: NULL
;
675 trav
->prb_node
= trav
->prb_node
->prb_link
[0];
676 while (trav
->prb_node
->prb_link
[1] != NULL
)
677 trav
->prb_node
= trav
->prb_node
->prb_link
[1];
678 return trav
->prb_node
->prb_data
;
682 /* Returns |trav|'s current item. */
684 prb_t_cur (struct prb_traverser
*trav
)
686 assert (trav
!= NULL
);
688 return trav
->prb_node
!= NULL
? trav
->prb_node
->prb_data
: NULL
;
691 /* Replaces the current item in |trav| by |new| and returns the item replaced.
692 |trav| must not have the null item selected.
693 The new item must not upset the ordering of the tree. */
695 prb_t_replace (struct prb_traverser
*trav
, void *new)
699 assert (trav
!= NULL
&& trav
->prb_node
!= NULL
&& new != NULL
);
700 old
= trav
->prb_node
->prb_data
;
701 trav
->prb_node
->prb_data
= new;
705 /* Destroys |new| with |prb_destroy (new, destroy)|,
706 first initializing right links in |new| that have
707 not yet been initialized at time of call. */
709 copy_error_recovery (struct prb_node
*q
,
710 struct prb_table
*new, prb_item_func
*destroy
)
712 assert (q
!= NULL
&& new != NULL
);
716 struct prb_node
*p
= q
;
721 if (p
== q
->prb_link
[0])
722 q
->prb_link
[1] = NULL
;
725 prb_destroy (new, destroy
);
728 /* Copies |org| to a newly created tree, which is returned.
729 If |copy != NULL|, each data item in |org| is first passed to |copy|,
730 and the return values are inserted into the tree;
731 |NULL| return values are taken as indications of failure.
732 On failure, destroys the partially created new tree,
733 applying |destroy|, if non-null, to each item in the new tree so far,
735 If |allocator != NULL|, it is used for allocation in the new tree.
736 Otherwise, the same allocator used for |org| is used. */
738 prb_copy (const struct prb_table
*org
, prb_copy_func
*copy
,
739 prb_item_func
*destroy
, struct libavl_allocator
*allocator
)
741 struct prb_table
*new;
742 const struct prb_node
*x
;
745 assert (org
!= NULL
);
746 new = prb_create (org
->prb_compare
, org
->prb_param
,
747 allocator
!= NULL
? allocator
: org
->prb_alloc
);
750 new->prb_count
= org
->prb_count
;
751 if (new->prb_count
== 0)
754 x
= (const struct prb_node
*) &org
->prb_root
;
755 y
= (struct prb_node
*) &new->prb_root
;
758 while (x
->prb_link
[0] != NULL
)
761 new->prb_alloc
->libavl_malloc (new->prb_alloc
,
762 sizeof *y
->prb_link
[0]);
763 if (y
->prb_link
[0] == NULL
)
765 if (y
!= (struct prb_node
*) &new->prb_root
)
768 y
->prb_link
[1] = NULL
;
771 copy_error_recovery (y
, new, destroy
);
774 y
->prb_link
[0]->prb_parent
= y
;
779 y
->prb_link
[0] = NULL
;
783 y
->prb_color
= x
->prb_color
;
785 y
->prb_data
= x
->prb_data
;
788 y
->prb_data
= copy (x
->prb_data
, org
->prb_param
);
789 if (y
->prb_data
== NULL
)
791 y
->prb_link
[1] = NULL
;
792 copy_error_recovery (y
, new, destroy
);
797 if (x
->prb_link
[1] != NULL
)
800 new->prb_alloc
->libavl_malloc (new->prb_alloc
,
801 sizeof *y
->prb_link
[1]);
802 if (y
->prb_link
[1] == NULL
)
804 copy_error_recovery (y
, new, destroy
);
807 y
->prb_link
[1]->prb_parent
= y
;
814 y
->prb_link
[1] = NULL
;
818 const struct prb_node
*w
= x
;
822 new->prb_root
->prb_parent
= NULL
;
827 if (w
== x
->prb_link
[0])
834 /* Frees storage allocated for |tree|.
835 If |destroy != NULL|, applies it to each data item in inorder. */
837 prb_destroy (struct prb_table
*tree
, prb_item_func
*destroy
)
839 struct prb_node
*p
, *q
;
841 assert (tree
!= NULL
);
843 for (p
= tree
->prb_root
; p
!= NULL
; p
= q
)
844 if (p
->prb_link
[0] == NULL
)
847 if (destroy
!= NULL
&& p
->prb_data
!= NULL
)
848 destroy (p
->prb_data
, tree
->prb_param
);
849 tree
->prb_alloc
->libavl_free (tree
->prb_alloc
, p
);
854 p
->prb_link
[0] = q
->prb_link
[1];
858 tree
->prb_alloc
->libavl_free (tree
->prb_alloc
, tree
);
861 /* Allocates |size| bytes of space using |malloc()|.
862 Returns a null pointer if allocation fails. */
864 prb_malloc (struct libavl_allocator
*allocator
, size_t size
)
866 assert (allocator
!= NULL
&& size
> 0);
867 return malloc (size
);
872 prb_free (struct libavl_allocator
*allocator
, void *block
)
874 assert (allocator
!= NULL
&& block
!= NULL
);
878 /* Default memory allocator that uses |malloc()| and |free()|. */
879 struct libavl_allocator prb_allocator_default
=
888 /* Asserts that |prb_insert()| succeeds at inserting |item| into |table|. */
890 (prb_assert_insert
) (struct prb_table
*table
, void *item
)
892 void **p
= prb_probe (table
, item
);
893 assert (p
!= NULL
&& *p
== item
);
896 /* Asserts that |prb_delete()| really removes |item| from |table|,
897 and returns the removed item. */
899 (prb_assert_delete
) (struct prb_table
*table
, void *item
)
901 void *p
= prb_delete (table
, item
);