1 /* Sequential list data type implemented by a binary tree.
2 Copyright (C) 2006-2007 Free Software Foundation, Inc.
3 Written by Bruno Haible <bruno@clisp.org>, 2006.
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
10 This program 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 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software Foundation,
17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
19 /* Common code of gl_avltree_list.c, gl_rbtree_list.c,
20 gl_avltreehash_list.c, gl_rbtreehash_list.c. */
23 gl_tree_create_empty (gl_list_implementation_t implementation,
24 gl_listelement_equals_fn equals_fn,
25 gl_listelement_hashcode_fn hashcode_fn,
26 gl_listelement_dispose_fn dispose_fn,
27 bool allow_duplicates)
29 struct gl_list_impl *list = XMALLOC (struct gl_list_impl);
31 list->base.vtable = implementation;
32 list->base.equals_fn = equals_fn;
33 list->base.hashcode_fn = hashcode_fn;
34 list->base.dispose_fn = dispose_fn;
35 list->base.allow_duplicates = allow_duplicates;
37 list->table_size = 11;
38 list->table = XCALLOC (list->table_size, gl_hash_entry_t);
46 gl_tree_size (gl_list_t list)
48 return (list->root != NULL ? list->root->branch_size : 0);
52 gl_tree_node_value (gl_list_t list, gl_list_node_t node)
58 gl_tree_next_node (gl_list_t list, gl_list_node_t node)
60 if (node->right != NULL)
63 while (node->left != NULL)
68 while (node->parent != NULL && node->parent->right == node)
76 gl_tree_previous_node (gl_list_t list, gl_list_node_t node)
78 if (node->left != NULL)
81 while (node->right != NULL)
86 while (node->parent != NULL && node->parent->left == node)
93 /* Return the node at the given position < gl_tree_size (list). */
94 static inline gl_list_node_t
95 node_at (gl_list_node_t root, size_t position)
97 /* Here we know that root != NULL. */
98 gl_list_node_t node = root;
102 if (node->left != NULL)
104 if (position < node->left->branch_size)
109 position -= node->left->branch_size;
120 gl_tree_get_at (gl_list_t list, size_t position)
122 gl_list_node_t node = list->root;
124 if (!(node != NULL && position < node->branch_size))
125 /* Invalid argument. */
127 node = node_at (node, position);
131 static gl_list_node_t
132 gl_tree_set_at (gl_list_t list, size_t position, const void *elt)
134 gl_list_node_t node = list->root;
136 if (!(node != NULL && position < node->branch_size))
137 /* Invalid argument. */
139 node = node_at (node, position);
141 if (elt != node->value)
143 size_t new_hashcode =
144 (list->base.hashcode_fn != NULL
145 ? list->base.hashcode_fn (elt)
146 : (size_t)(uintptr_t) elt);
148 if (new_hashcode != node->h.hashcode)
150 remove_from_bucket (list, node);
152 node->h.hashcode = new_hashcode;
153 add_to_bucket (list, node);
166 static gl_list_node_t
167 gl_tree_search_from_to (gl_list_t list, size_t start_index, size_t end_index,
170 if (!(start_index <= end_index
171 && end_index <= (list->root != NULL ? list->root->branch_size : 0)))
172 /* Invalid arguments. */
175 gl_listelement_equals_fn equals = list->base.equals_fn;
176 /* Iterate across all elements. */
177 gl_list_node_t node = list->root;
179 iterstack_item_t *stack_ptr = &stack[0];
182 if (start_index == 0)
184 /* Consider all elements. */
187 /* Descend on left branch. */
192 stack_ptr->node = node;
193 stack_ptr->rightp = 0;
197 /* Climb up again. */
200 if (stack_ptr == &stack[0])
203 if (!stack_ptr->rightp)
206 node = stack_ptr->node;
207 /* Test against current element. */
208 if (equals != NULL ? equals (elt, node->value) : elt == node->value)
211 if (index >= end_index)
213 /* Descend on right branch. */
214 stack_ptr->rightp = 1;
221 /* Consider only elements at indices >= start_index.
222 In this case, rightp contains the difference between the start_index
223 for the parent node and the one for the child node (0 when the child
224 node is the parent's left child, > 0 when the child is the parent's
228 /* Descend on left branch. */
233 if (node->branch_size <= start_index)
235 stack_ptr->node = node;
236 stack_ptr->rightp = 0;
240 /* Climb up again. */
243 if (stack_ptr == &stack[0])
246 if (!stack_ptr->rightp)
248 start_index += stack_ptr->rightp;
250 node = stack_ptr->node;
252 size_t left_branch_size1 =
253 (node->left != NULL ? node->left->branch_size : 0) + 1;
254 if (start_index < left_branch_size1)
256 /* Test against current element. */
257 if (equals != NULL ? equals (elt, node->value) : elt == node->value)
259 /* Now that we have considered all indices < left_branch_size1,
260 we can increment start_index. */
261 start_index = left_branch_size1;
264 if (index >= end_index)
266 /* Descend on right branch. */
267 start_index -= left_branch_size1;
268 stack_ptr->rightp = left_branch_size1;
278 gl_tree_indexof_from_to (gl_list_t list, size_t start_index, size_t end_index,
281 if (!(start_index <= end_index
282 && end_index <= (list->root != NULL ? list->root->branch_size : 0)))
283 /* Invalid arguments. */
286 gl_listelement_equals_fn equals = list->base.equals_fn;
287 /* Iterate across all elements. */
288 gl_list_node_t node = list->root;
290 iterstack_item_t *stack_ptr = &stack[0];
293 if (start_index == 0)
295 /* Consider all elements. */
298 /* Descend on left branch. */
303 stack_ptr->node = node;
304 stack_ptr->rightp = 0;
308 /* Climb up again. */
311 if (stack_ptr == &stack[0])
314 if (!stack_ptr->rightp)
317 node = stack_ptr->node;
318 /* Test against current element. */
319 if (equals != NULL ? equals (elt, node->value) : elt == node->value)
322 if (index >= end_index)
324 /* Descend on right branch. */
325 stack_ptr->rightp = 1;
332 /* Consider only elements at indices >= start_index.
333 In this case, rightp contains the difference between the start_index
334 for the parent node and the one for the child node (0 when the child
335 node is the parent's left child, > 0 when the child is the parent's
339 /* Descend on left branch. */
344 if (node->branch_size <= start_index)
346 stack_ptr->node = node;
347 stack_ptr->rightp = 0;
351 /* Climb up again. */
354 if (stack_ptr == &stack[0])
357 if (!stack_ptr->rightp)
359 start_index += stack_ptr->rightp;
361 node = stack_ptr->node;
363 size_t left_branch_size1 =
364 (node->left != NULL ? node->left->branch_size : 0) + 1;
365 if (start_index < left_branch_size1)
367 /* Test against current element. */
368 if (equals != NULL ? equals (elt, node->value) : elt == node->value)
370 /* Now that we have considered all indices < left_branch_size1,
371 we can increment start_index. */
372 start_index = left_branch_size1;
375 if (index >= end_index)
377 /* Descend on right branch. */
378 start_index -= left_branch_size1;
379 stack_ptr->rightp = left_branch_size1;
390 static gl_list_node_t
391 gl_tree_add_at (gl_list_t list, size_t position, const void *elt)
393 size_t count = (list->root != NULL ? list->root->branch_size : 0);
395 if (!(position <= count))
396 /* Invalid argument. */
398 if (position == count)
399 return gl_tree_add_last (list, elt);
401 return gl_tree_add_before (list, node_at (list->root, position), elt);
405 gl_tree_remove_at (gl_list_t list, size_t position)
407 gl_list_node_t node = list->root;
409 if (!(node != NULL && position < node->branch_size))
410 /* Invalid argument. */
412 node = node_at (node, position);
413 return gl_tree_remove_node (list, node);
417 gl_tree_remove (gl_list_t list, const void *elt)
419 if (list->root != NULL)
421 gl_list_node_t node =
422 gl_tree_search_from_to (list, 0, list->root->branch_size, elt);
425 return gl_tree_remove_node (list, node);
433 gl_tree_list_free (gl_list_t list)
435 /* Iterate across all elements in post-order. */
436 gl_list_node_t node = list->root;
438 iterstack_item_t *stack_ptr = &stack[0];
442 /* Descend on left branch. */
447 stack_ptr->node = node;
448 stack_ptr->rightp = false;
452 /* Climb up again. */
455 if (stack_ptr == &stack[0])
458 node = stack_ptr->node;
459 if (!stack_ptr->rightp)
461 /* Free the current node. */
462 if (list->base.dispose_fn != NULL)
463 list->base.dispose_fn (node->value);
466 /* Descend on right branch. */
467 stack_ptr->rightp = true;
477 /* --------------------- gl_list_iterator_t Data Type --------------------- */
479 static gl_list_iterator_t
480 gl_tree_iterator (gl_list_t list)
482 gl_list_iterator_t result;
485 result.vtable = list->base.vtable;
487 /* Start node is the leftmost node. */
490 while (node->left != NULL)
493 /* End point is past the rightmost node. */
504 static gl_list_iterator_t
505 gl_tree_iterator_from_to (gl_list_t list, size_t start_index, size_t end_index)
507 size_t count = (list->root != NULL ? list->root->branch_size : 0);
508 gl_list_iterator_t result;
510 if (!(start_index <= end_index && end_index <= count))
511 /* Invalid arguments. */
513 result.vtable = list->base.vtable;
515 /* Start node is the node at position start_index. */
516 result.p = (start_index < count ? node_at (list->root, start_index) : NULL);
517 /* End point is the node at position end_index. */
518 result.q = (end_index < count ? node_at (list->root, end_index) : NULL);
529 gl_tree_iterator_next (gl_list_iterator_t *iterator,
530 const void **eltp, gl_list_node_t *nodep)
532 if (iterator->p != iterator->q)
534 gl_list_node_t node = (gl_list_node_t) iterator->p;
538 /* Advance to the next node. */
539 if (node->right != NULL)
542 while (node->left != NULL)
547 while (node->parent != NULL && node->parent->right == node)
559 gl_tree_iterator_free (gl_list_iterator_t *iterator)
563 /* ---------------------- Sorted gl_list_t Data Type ---------------------- */
565 static gl_list_node_t
566 gl_tree_sortedlist_search (gl_list_t list, gl_listelement_compar_fn compar,
571 for (node = list->root; node != NULL; )
573 int cmp = compar (node->value, elt);
581 /* We have an element equal to ELT. But we need the leftmost such
583 gl_list_node_t found = node;
585 for (; node != NULL; )
587 int cmp2 = compar (node->value, elt);
592 /* The list was not sorted. */
606 static gl_list_node_t
607 gl_tree_sortedlist_search_from_to (gl_list_t list,
608 gl_listelement_compar_fn compar,
609 size_t low, size_t high,
615 && high <= (list->root != NULL ? list->root->branch_size : 0)))
616 /* Invalid arguments. */
619 for (node = list->root; node != NULL; )
621 size_t left_branch_size =
622 (node->left != NULL ? node->left->branch_size : 0);
624 if (low > left_branch_size)
626 low -= left_branch_size + 1;
627 high -= left_branch_size + 1;
630 else if (high <= left_branch_size)
634 /* Here low <= left_branch_size < high. */
635 int cmp = compar (node->value, elt);
640 high -= left_branch_size + 1;
647 /* We have an element equal to ELT. But we need the leftmost
649 gl_list_node_t found = node;
651 for (; node != NULL; )
653 size_t left_branch_size2 =
654 (node->left != NULL ? node->left->branch_size : 0);
656 if (low > left_branch_size2)
658 low -= left_branch_size2 + 1;
663 /* Here low <= left_branch_size2. */
664 int cmp2 = compar (node->value, elt);
672 /* The list was not sorted. */
689 gl_tree_sortedlist_indexof (gl_list_t list, gl_listelement_compar_fn compar,
695 for (node = list->root, position = 0; node != NULL; )
697 int cmp = compar (node->value, elt);
701 if (node->left != NULL)
702 position += node->left->branch_size;
710 /* We have an element equal to ELT. But we need the leftmost such
712 size_t found_position =
713 position + (node->left != NULL ? node->left->branch_size : 0);
715 for (; node != NULL; )
717 int cmp2 = compar (node->value, elt);
721 if (node->left != NULL)
722 position += node->left->branch_size;
727 /* The list was not sorted. */
733 + (node->left != NULL ? node->left->branch_size : 0);
737 return found_position;
744 gl_tree_sortedlist_indexof_from_to (gl_list_t list,
745 gl_listelement_compar_fn compar,
746 size_t low, size_t high,
753 && high <= (list->root != NULL ? list->root->branch_size : 0)))
754 /* Invalid arguments. */
757 for (node = list->root, position = 0; node != NULL; )
759 size_t left_branch_size =
760 (node->left != NULL ? node->left->branch_size : 0);
762 if (low > left_branch_size)
764 low -= left_branch_size + 1;
765 high -= left_branch_size + 1;
766 position += left_branch_size + 1;
769 else if (high <= left_branch_size)
773 /* Here low <= left_branch_size < high. */
774 int cmp = compar (node->value, elt);
779 high -= left_branch_size + 1;
780 position += left_branch_size + 1;
787 /* We have an element equal to ELT. But we need the leftmost
789 size_t found_position =
790 position + (node->left != NULL ? node->left->branch_size : 0);
792 for (; node != NULL; )
794 size_t left_branch_size2 =
795 (node->left != NULL ? node->left->branch_size : 0);
797 if (low > left_branch_size2)
799 low -= left_branch_size2 + 1;
804 /* Here low <= left_branch_size2. */
805 int cmp2 = compar (node->value, elt);
809 position += left_branch_size2 + 1;
813 /* The list was not sorted. */
817 found_position = position + left_branch_size2;
822 return found_position;
829 static gl_list_node_t
830 gl_tree_sortedlist_add (gl_list_t list, gl_listelement_compar_fn compar,
833 gl_list_node_t node = list->root;
836 return gl_tree_add_first (list, elt);
840 int cmp = compar (node->value, elt);
844 if (node->right == NULL)
845 return gl_tree_add_after (list, node, elt);
850 if (node->left == NULL)
851 return gl_tree_add_before (list, node, elt);
855 return gl_tree_add_before (list, node, elt);
860 gl_tree_sortedlist_remove (gl_list_t list, gl_listelement_compar_fn compar,
863 gl_list_node_t node = gl_tree_sortedlist_search (list, compar, elt);
865 return gl_tree_remove_node (list, node);