1 /* Sequential list data type implemented by a binary tree.
2 Copyright (C) 2006-2025 Free Software Foundation, Inc.
3 Written by Bruno Haible <bruno@clisp.org>, 2006.
5 This file is free software: you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as
7 published by the Free Software Foundation; either version 2.1 of the
8 License, or (at your option) any later version.
10 This file is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public License
16 along with this program. If not, see <https://www.gnu.org/licenses/>. */
18 /* Common code of gl_avltree_list.c, gl_rbtree_list.c,
19 gl_avltreehash_list.c, gl_rbtreehash_list.c. */
22 gl_tree_nx_create_empty (gl_list_implementation_t implementation
,
23 gl_listelement_equals_fn equals_fn
,
24 gl_listelement_hashcode_fn hashcode_fn
,
25 gl_listelement_dispose_fn dispose_fn
,
26 bool allow_duplicates
)
28 struct gl_list_impl
*list
= (struct gl_list_impl
*) malloc (sizeof (struct gl_list_impl
));
33 list
->base
.vtable
= implementation
;
34 list
->base
.equals_fn
= equals_fn
;
35 list
->base
.hashcode_fn
= hashcode_fn
;
36 list
->base
.dispose_fn
= dispose_fn
;
37 list
->base
.allow_duplicates
= allow_duplicates
;
39 list
->table_size
= 11;
41 (gl_hash_entry_t
*) calloc (list
->table_size
, sizeof (gl_hash_entry_t
));
42 if (list
->table
== NULL
)
56 static size_t _GL_ATTRIBUTE_PURE
57 gl_tree_size (gl_list_t list
)
59 return (list
->root
!= NULL
? list
->root
->branch_size
: 0);
62 static const void * _GL_ATTRIBUTE_PURE
63 gl_tree_node_value (_GL_ATTRIBUTE_MAYBE_UNUSED gl_list_t list
,
70 gl_tree_node_nx_set_value (_GL_ATTRIBUTE_MAYBE_UNUSED gl_list_t list
,
71 gl_list_node_t node
, const void *elt
)
74 if (elt
!= node
->value
)
77 (list
->base
.hashcode_fn
!= NULL
78 ? list
->base
.hashcode_fn (elt
)
79 : (size_t)(uintptr_t) elt
);
81 if (new_hashcode
!= node
->h
.hashcode
)
83 remove_from_bucket (list
, node
);
85 node
->h
.hashcode
= new_hashcode
;
86 if (add_to_bucket (list
, node
) < 0)
88 /* Out of memory. We removed node from a bucket but cannot add
89 it to another bucket. In order to avoid inconsistencies, we
90 must remove node entirely from the list. */
91 gl_tree_remove_node_from_tree (list
, node
);
105 static gl_list_node_t _GL_ATTRIBUTE_PURE
106 gl_tree_next_node (_GL_ATTRIBUTE_MAYBE_UNUSED gl_list_t list
,
109 if (node
->right
!= NULL
)
112 while (node
->left
!= NULL
)
117 while (node
->parent
!= NULL
&& node
->parent
->right
== node
)
124 static gl_list_node_t _GL_ATTRIBUTE_PURE
125 gl_tree_previous_node (_GL_ATTRIBUTE_MAYBE_UNUSED gl_list_t list
,
128 if (node
->left
!= NULL
)
131 while (node
->right
!= NULL
)
136 while (node
->parent
!= NULL
&& node
->parent
->left
== node
)
143 static gl_list_node_t _GL_ATTRIBUTE_PURE
144 gl_tree_first_node (_GL_ATTRIBUTE_MAYBE_UNUSED gl_list_t list
)
146 gl_list_node_t node
= list
->root
;
150 while (node
->left
!= NULL
)
156 static gl_list_node_t _GL_ATTRIBUTE_PURE
157 gl_tree_last_node (_GL_ATTRIBUTE_MAYBE_UNUSED gl_list_t list
)
159 gl_list_node_t node
= list
->root
;
163 while (node
->right
!= NULL
)
169 /* Returns the node at the given position < gl_tree_size (list). */
170 static gl_list_node_t _GL_ATTRIBUTE_PURE
171 node_at (gl_list_node_t root
, size_t position
)
173 /* Here we know that root != NULL. */
174 gl_list_node_t node
= root
;
178 if (node
->left
!= NULL
)
180 if (position
< node
->left
->branch_size
)
185 position
-= node
->left
->branch_size
;
195 static const void * _GL_ATTRIBUTE_PURE
196 gl_tree_get_at (gl_list_t list
, size_t position
)
198 gl_list_node_t node
= list
->root
;
200 if (!(node
!= NULL
&& position
< node
->branch_size
))
201 /* Invalid argument. */
203 node
= node_at (node
, position
);
207 static gl_list_node_t
208 gl_tree_nx_set_at (gl_list_t list
, size_t position
, const void *elt
)
210 gl_list_node_t node
= list
->root
;
212 if (!(node
!= NULL
&& position
< node
->branch_size
))
213 /* Invalid argument. */
215 node
= node_at (node
, position
);
217 if (elt
!= node
->value
)
219 size_t new_hashcode
=
220 (list
->base
.hashcode_fn
!= NULL
221 ? list
->base
.hashcode_fn (elt
)
222 : (size_t)(uintptr_t) elt
);
224 if (new_hashcode
!= node
->h
.hashcode
)
226 remove_from_bucket (list
, node
);
228 node
->h
.hashcode
= new_hashcode
;
229 if (add_to_bucket (list
, node
) < 0)
231 /* Out of memory. We removed node from a bucket but cannot add
232 it to another bucket. In order to avoid inconsistencies, we
233 must remove node entirely from the list. */
234 gl_tree_remove_node_from_tree (list
, node
);
250 static gl_list_node_t _GL_ATTRIBUTE_PURE
251 gl_tree_search_from_to (gl_list_t list
, size_t start_index
, size_t end_index
,
254 if (!(start_index
<= end_index
255 && end_index
<= (list
->root
!= NULL
? list
->root
->branch_size
: 0)))
256 /* Invalid arguments. */
259 gl_listelement_equals_fn equals
= list
->base
.equals_fn
;
260 /* Iterate across all elements. */
261 gl_list_node_t node
= list
->root
;
263 iterstack_item_t
*stack_ptr
= &stack
[0];
266 if (start_index
== 0)
268 /* Consider all elements. */
271 /* Descend on left branch. */
276 stack_ptr
->node
= node
;
277 stack_ptr
->rightp
= 0;
281 /* Climb up again. */
284 if (stack_ptr
== &stack
[0])
287 if (!stack_ptr
->rightp
)
290 node
= stack_ptr
->node
;
291 /* Test against current element. */
292 if (equals
!= NULL
? equals (elt
, node
->value
) : elt
== node
->value
)
295 if (index
>= end_index
)
297 /* Descend on right branch. */
298 stack_ptr
->rightp
= 1;
305 /* Consider only elements at indices >= start_index.
306 In this case, rightp contains the difference between the start_index
307 for the parent node and the one for the child node (0 when the child
308 node is the parent's left child, > 0 when the child is the parent's
312 /* Descend on left branch. */
317 if (node
->branch_size
<= start_index
)
319 stack_ptr
->node
= node
;
320 stack_ptr
->rightp
= 0;
324 /* Climb up again. */
327 if (stack_ptr
== &stack
[0])
330 if (!stack_ptr
->rightp
)
332 start_index
+= stack_ptr
->rightp
;
334 node
= stack_ptr
->node
;
336 size_t left_branch_size1
=
337 (node
->left
!= NULL
? node
->left
->branch_size
: 0) + 1;
338 if (start_index
< left_branch_size1
)
340 /* Test against current element. */
341 if (equals
!= NULL
? equals (elt
, node
->value
) : elt
== node
->value
)
343 /* Now that we have considered all indices < left_branch_size1,
344 we can increment start_index. */
345 start_index
= left_branch_size1
;
348 if (index
>= end_index
)
350 /* Descend on right branch. */
351 start_index
-= left_branch_size1
;
352 stack_ptr
->rightp
= left_branch_size1
;
361 static size_t _GL_ATTRIBUTE_PURE
362 gl_tree_indexof_from_to (gl_list_t list
, size_t start_index
, size_t end_index
,
365 if (!(start_index
<= end_index
366 && end_index
<= (list
->root
!= NULL
? list
->root
->branch_size
: 0)))
367 /* Invalid arguments. */
370 gl_listelement_equals_fn equals
= list
->base
.equals_fn
;
371 /* Iterate across all elements. */
372 gl_list_node_t node
= list
->root
;
374 iterstack_item_t
*stack_ptr
= &stack
[0];
377 if (start_index
== 0)
379 /* Consider all elements. */
382 /* Descend on left branch. */
387 stack_ptr
->node
= node
;
388 stack_ptr
->rightp
= 0;
392 /* Climb up again. */
395 if (stack_ptr
== &stack
[0])
398 if (!stack_ptr
->rightp
)
401 node
= stack_ptr
->node
;
402 /* Test against current element. */
403 if (equals
!= NULL
? equals (elt
, node
->value
) : elt
== node
->value
)
406 if (index
>= end_index
)
408 /* Descend on right branch. */
409 stack_ptr
->rightp
= 1;
416 /* Consider only elements at indices >= start_index.
417 In this case, rightp contains the difference between the start_index
418 for the parent node and the one for the child node (0 when the child
419 node is the parent's left child, > 0 when the child is the parent's
423 /* Descend on left branch. */
428 if (node
->branch_size
<= start_index
)
430 stack_ptr
->node
= node
;
431 stack_ptr
->rightp
= 0;
435 /* Climb up again. */
438 if (stack_ptr
== &stack
[0])
441 if (!stack_ptr
->rightp
)
443 start_index
+= stack_ptr
->rightp
;
445 node
= stack_ptr
->node
;
447 size_t left_branch_size1
=
448 (node
->left
!= NULL
? node
->left
->branch_size
: 0) + 1;
449 if (start_index
< left_branch_size1
)
451 /* Test against current element. */
452 if (equals
!= NULL
? equals (elt
, node
->value
) : elt
== node
->value
)
454 /* Now that we have considered all indices < left_branch_size1,
455 we can increment start_index. */
456 start_index
= left_branch_size1
;
459 if (index
>= end_index
)
461 /* Descend on right branch. */
462 start_index
-= left_branch_size1
;
463 stack_ptr
->rightp
= left_branch_size1
;
474 static gl_list_node_t
475 gl_tree_nx_add_at (gl_list_t list
, size_t position
, const void *elt
)
477 size_t count
= (list
->root
!= NULL
? list
->root
->branch_size
: 0);
479 if (!(position
<= count
))
480 /* Invalid argument. */
482 if (position
== count
)
483 return gl_tree_nx_add_last (list
, elt
);
485 return gl_tree_nx_add_before (list
, node_at (list
->root
, position
), elt
);
489 gl_tree_remove_node (gl_list_t list
, gl_list_node_t node
)
492 /* Remove node from the hash table.
493 Note that this is only possible _before_ the node is removed from the
494 tree structure, because remove_from_bucket() uses node_position(). */
495 remove_from_bucket (list
, node
);
498 gl_tree_remove_node_from_tree (list
, node
);
500 if (list
->base
.dispose_fn
!= NULL
)
501 list
->base
.dispose_fn (node
->value
);
507 gl_tree_remove_at (gl_list_t list
, size_t position
)
509 gl_list_node_t node
= list
->root
;
511 if (!(node
!= NULL
&& position
< node
->branch_size
))
512 /* Invalid argument. */
514 node
= node_at (node
, position
);
515 return gl_tree_remove_node (list
, node
);
519 gl_tree_remove (gl_list_t list
, const void *elt
)
521 if (list
->root
!= NULL
)
523 gl_list_node_t node
=
524 gl_tree_search_from_to (list
, 0, list
->root
->branch_size
, elt
);
527 return gl_tree_remove_node (list
, node
);
535 gl_tree_list_free (gl_list_t list
)
537 /* Iterate across all elements in post-order. */
538 gl_list_node_t node
= list
->root
;
540 iterstack_item_t
*stack_ptr
= &stack
[0];
544 /* Descend on left branch. */
549 stack_ptr
->node
= node
;
550 stack_ptr
->rightp
= false;
554 /* Climb up again. */
557 if (stack_ptr
== &stack
[0])
560 node
= stack_ptr
->node
;
561 if (!stack_ptr
->rightp
)
563 /* Free the current node. */
564 if (list
->base
.dispose_fn
!= NULL
)
565 list
->base
.dispose_fn (node
->value
);
568 /* Descend on right branch. */
569 stack_ptr
->rightp
= true;
579 /* --------------------- gl_list_iterator_t Data Type --------------------- */
581 static gl_list_iterator_t _GL_ATTRIBUTE_PURE
582 gl_tree_iterator (gl_list_t list
)
584 gl_list_iterator_t result
;
587 result
.vtable
= list
->base
.vtable
;
589 /* Start node is the leftmost node. */
592 while (node
->left
!= NULL
)
595 /* End point is past the rightmost node. */
597 #if defined GCC_LINT || defined lint
606 static gl_list_iterator_t _GL_ATTRIBUTE_PURE
607 gl_tree_iterator_from_to (gl_list_t list
, size_t start_index
, size_t end_index
)
609 size_t count
= (list
->root
!= NULL
? list
->root
->branch_size
: 0);
610 gl_list_iterator_t result
;
612 if (!(start_index
<= end_index
&& end_index
<= count
))
613 /* Invalid arguments. */
615 result
.vtable
= list
->base
.vtable
;
617 /* Start node is the node at position start_index. */
618 result
.p
= (start_index
< count
? node_at (list
->root
, start_index
) : NULL
);
619 /* End point is the node at position end_index. */
620 result
.q
= (end_index
< count
? node_at (list
->root
, end_index
) : NULL
);
621 #if defined GCC_LINT || defined lint
631 gl_tree_iterator_next (gl_list_iterator_t
*iterator
,
632 const void **eltp
, gl_list_node_t
*nodep
)
634 if (iterator
->p
!= iterator
->q
)
636 gl_list_node_t node
= (gl_list_node_t
) iterator
->p
;
640 /* Advance to the next node. */
641 if (node
->right
!= NULL
)
644 while (node
->left
!= NULL
)
649 while (node
->parent
!= NULL
&& node
->parent
->right
== node
)
661 gl_tree_iterator_free (_GL_ATTRIBUTE_MAYBE_UNUSED gl_list_iterator_t
*iterator
)
665 /* ---------------------- Sorted gl_list_t Data Type ---------------------- */
667 static gl_list_node_t _GL_ATTRIBUTE_PURE
668 gl_tree_sortedlist_search (gl_list_t list
, gl_listelement_compar_fn compar
,
673 for (node
= list
->root
; node
!= NULL
; )
675 int cmp
= compar (node
->value
, elt
);
683 /* We have an element equal to ELT. But we need the leftmost such
685 gl_list_node_t found
= node
;
687 for (; node
!= NULL
; )
689 int cmp2
= compar (node
->value
, elt
);
694 /* The list was not sorted. */
708 static gl_list_node_t _GL_ATTRIBUTE_PURE
709 gl_tree_sortedlist_search_from_to (gl_list_t list
,
710 gl_listelement_compar_fn compar
,
711 size_t low
, size_t high
,
717 && high
<= (list
->root
!= NULL
? list
->root
->branch_size
: 0)))
718 /* Invalid arguments. */
721 for (node
= list
->root
; node
!= NULL
; )
723 size_t left_branch_size
=
724 (node
->left
!= NULL
? node
->left
->branch_size
: 0);
726 if (low
> left_branch_size
)
728 low
-= left_branch_size
+ 1;
729 high
-= left_branch_size
+ 1;
732 else if (high
<= left_branch_size
)
736 /* Here low <= left_branch_size < high. */
737 int cmp
= compar (node
->value
, elt
);
742 high
-= left_branch_size
+ 1;
749 /* We have an element equal to ELT. But we need the leftmost
751 gl_list_node_t found
= node
;
753 for (; node
!= NULL
; )
755 size_t left_branch_size2
=
756 (node
->left
!= NULL
? node
->left
->branch_size
: 0);
758 if (low
> left_branch_size2
)
760 low
-= left_branch_size2
+ 1;
765 /* Here low <= left_branch_size2. */
766 int cmp2
= compar (node
->value
, elt
);
774 /* The list was not sorted. */
790 static size_t _GL_ATTRIBUTE_PURE
791 gl_tree_sortedlist_indexof (gl_list_t list
, gl_listelement_compar_fn compar
,
797 for (node
= list
->root
, position
= 0; node
!= NULL
; )
799 int cmp
= compar (node
->value
, elt
);
803 if (node
->left
!= NULL
)
804 position
+= node
->left
->branch_size
;
812 /* We have an element equal to ELT. But we need the leftmost such
814 size_t found_position
=
815 position
+ (node
->left
!= NULL
? node
->left
->branch_size
: 0);
817 for (; node
!= NULL
; )
819 int cmp2
= compar (node
->value
, elt
);
823 if (node
->left
!= NULL
)
824 position
+= node
->left
->branch_size
;
829 /* The list was not sorted. */
835 + (node
->left
!= NULL
? node
->left
->branch_size
: 0);
839 return found_position
;
845 static size_t _GL_ATTRIBUTE_PURE
846 gl_tree_sortedlist_indexof_from_to (gl_list_t list
,
847 gl_listelement_compar_fn compar
,
848 size_t low
, size_t high
,
855 && high
<= (list
->root
!= NULL
? list
->root
->branch_size
: 0)))
856 /* Invalid arguments. */
859 for (node
= list
->root
, position
= 0; node
!= NULL
; )
861 size_t left_branch_size
=
862 (node
->left
!= NULL
? node
->left
->branch_size
: 0);
864 if (low
> left_branch_size
)
866 low
-= left_branch_size
+ 1;
867 high
-= left_branch_size
+ 1;
868 position
+= left_branch_size
+ 1;
871 else if (high
<= left_branch_size
)
875 /* Here low <= left_branch_size < high. */
876 int cmp
= compar (node
->value
, elt
);
881 high
-= left_branch_size
+ 1;
882 position
+= left_branch_size
+ 1;
889 /* We have an element equal to ELT. But we need the leftmost
891 size_t found_position
=
892 position
+ (node
->left
!= NULL
? node
->left
->branch_size
: 0);
894 for (; node
!= NULL
; )
896 size_t left_branch_size2
=
897 (node
->left
!= NULL
? node
->left
->branch_size
: 0);
899 if (low
> left_branch_size2
)
901 low
-= left_branch_size2
+ 1;
906 /* Here low <= left_branch_size2. */
907 int cmp2
= compar (node
->value
, elt
);
911 position
+= left_branch_size2
+ 1;
915 /* The list was not sorted. */
919 found_position
= position
+ left_branch_size2
;
924 return found_position
;
931 static gl_list_node_t
932 gl_tree_sortedlist_nx_add (gl_list_t list
, gl_listelement_compar_fn compar
,
935 gl_list_node_t node
= list
->root
;
938 return gl_tree_nx_add_first (list
, elt
);
942 int cmp
= compar (node
->value
, elt
);
946 if (node
->right
== NULL
)
947 return gl_tree_nx_add_after (list
, node
, elt
);
952 if (node
->left
== NULL
)
953 return gl_tree_nx_add_before (list
, node
, elt
);
957 return gl_tree_nx_add_before (list
, node
, elt
);
962 gl_tree_sortedlist_remove (gl_list_t list
, gl_listelement_compar_fn compar
,
965 gl_list_node_t node
= gl_tree_sortedlist_search (list
, compar
, elt
);
967 return gl_tree_remove_node (list
, node
);