1 /* Sequential list data type implemented by a binary tree.
2 Copyright (C) 2006 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 bool allow_duplicates)
28 struct gl_list_impl *list = XMALLOC (struct gl_list_impl);
30 list->base.vtable = implementation;
31 list->base.equals_fn = equals_fn;
32 list->base.hashcode_fn = hashcode_fn;
33 list->base.allow_duplicates = allow_duplicates;
35 list->table_size = 11;
36 list->table = XCALLOC (list->table_size, gl_hash_entry_t);
44 gl_tree_size (gl_list_t list)
46 return (list->root != NULL ? list->root->branch_size : 0);
50 gl_tree_node_value (gl_list_t list, gl_list_node_t node)
56 gl_tree_next_node (gl_list_t list, gl_list_node_t node)
58 if (node->right != NULL)
61 while (node->left != NULL)
66 while (node->parent != NULL && node->parent->right == node)
74 gl_tree_previous_node (gl_list_t list, gl_list_node_t node)
76 if (node->left != NULL)
79 while (node->right != NULL)
84 while (node->parent != NULL && node->parent->left == node)
91 /* Return the node at the given position < gl_tree_size (list). */
92 static inline gl_list_node_t
93 node_at (gl_list_node_t root, size_t position)
95 /* Here we know that root != NULL. */
96 gl_list_node_t node = root;
100 if (node->left != NULL)
102 if (position < node->left->branch_size)
107 position -= node->left->branch_size;
118 gl_tree_get_at (gl_list_t list, size_t position)
120 gl_list_node_t node = list->root;
122 if (!(node != NULL && position < node->branch_size))
123 /* Invalid argument. */
125 node = node_at (node, position);
129 static gl_list_node_t
130 gl_tree_set_at (gl_list_t list, size_t position, const void *elt)
132 gl_list_node_t node = list->root;
134 if (!(node != NULL && position < node->branch_size))
135 /* Invalid argument. */
137 node = node_at (node, position);
139 if (elt != node->value)
141 size_t new_hashcode =
142 (list->base.hashcode_fn != NULL
143 ? list->base.hashcode_fn (elt)
144 : (size_t)(uintptr_t) elt);
146 if (new_hashcode != node->h.hashcode)
148 remove_from_bucket (list, node);
150 node->h.hashcode = new_hashcode;
151 add_to_bucket (list, node);
164 static gl_list_node_t
165 gl_tree_search_from_to (gl_list_t list, size_t start_index, size_t end_index,
168 if (!(start_index <= end_index
169 && end_index <= (list->root != NULL ? list->root->branch_size : 0)))
170 /* Invalid arguments. */
173 gl_listelement_equals_fn equals = list->base.equals_fn;
174 /* Iterate across all elements. */
175 gl_list_node_t node = list->root;
177 iterstack_item_t *stack_ptr = &stack[0];
180 if (start_index == 0)
182 /* Consider all elements. */
185 /* Descend on left branch. */
190 stack_ptr->node = node;
191 stack_ptr->rightp = 0;
195 /* Climb up again. */
198 if (stack_ptr == &stack[0])
201 if (!stack_ptr->rightp)
204 node = stack_ptr->node;
205 /* Test against current element. */
206 if (equals != NULL ? equals (elt, node->value) : elt == node->value)
209 if (index >= end_index)
211 /* Descend on right branch. */
212 stack_ptr->rightp = 1;
219 /* Consider only elements at indices >= start_index.
220 In this case, rightp contains the difference between the start_index
221 for the parent node and the one for the child node (0 when the child
222 node is the parent's left child, > 0 when the child is the parent's
226 /* Descend on left branch. */
231 if (node->branch_size <= start_index)
233 stack_ptr->node = node;
234 stack_ptr->rightp = 0;
238 /* Climb up again. */
241 if (stack_ptr == &stack[0])
244 if (!stack_ptr->rightp)
246 start_index += stack_ptr->rightp;
248 node = stack_ptr->node;
250 size_t left_branch_size1 =
251 (node->left != NULL ? node->left->branch_size : 0) + 1;
252 if (start_index < left_branch_size1)
254 /* Test against current element. */
255 if (equals != NULL ? equals (elt, node->value) : elt == node->value)
257 /* Now that we have considered all indices < left_branch_size1,
258 we can increment start_index. */
259 start_index = left_branch_size1;
262 if (index >= end_index)
264 /* Descend on right branch. */
265 start_index -= left_branch_size1;
266 stack_ptr->rightp = left_branch_size1;
276 gl_tree_indexof_from_to (gl_list_t list, size_t start_index, size_t end_index,
279 if (!(start_index <= end_index
280 && end_index <= (list->root != NULL ? list->root->branch_size : 0)))
281 /* Invalid arguments. */
284 gl_listelement_equals_fn equals = list->base.equals_fn;
285 /* Iterate across all elements. */
286 gl_list_node_t node = list->root;
288 iterstack_item_t *stack_ptr = &stack[0];
291 if (start_index == 0)
293 /* Consider all elements. */
296 /* Descend on left branch. */
301 stack_ptr->node = node;
302 stack_ptr->rightp = 0;
306 /* Climb up again. */
309 if (stack_ptr == &stack[0])
312 if (!stack_ptr->rightp)
315 node = stack_ptr->node;
316 /* Test against current element. */
317 if (equals != NULL ? equals (elt, node->value) : elt == node->value)
320 if (index >= end_index)
322 /* Descend on right branch. */
323 stack_ptr->rightp = 1;
330 /* Consider only elements at indices >= start_index.
331 In this case, rightp contains the difference between the start_index
332 for the parent node and the one for the child node (0 when the child
333 node is the parent's left child, > 0 when the child is the parent's
337 /* Descend on left branch. */
342 if (node->branch_size <= start_index)
344 stack_ptr->node = node;
345 stack_ptr->rightp = 0;
349 /* Climb up again. */
352 if (stack_ptr == &stack[0])
355 if (!stack_ptr->rightp)
357 start_index += stack_ptr->rightp;
359 node = stack_ptr->node;
361 size_t left_branch_size1 =
362 (node->left != NULL ? node->left->branch_size : 0) + 1;
363 if (start_index < left_branch_size1)
365 /* Test against current element. */
366 if (equals != NULL ? equals (elt, node->value) : elt == node->value)
368 /* Now that we have considered all indices < left_branch_size1,
369 we can increment start_index. */
370 start_index = left_branch_size1;
373 if (index >= end_index)
375 /* Descend on right branch. */
376 start_index -= left_branch_size1;
377 stack_ptr->rightp = left_branch_size1;
388 static gl_list_node_t
389 gl_tree_add_at (gl_list_t list, size_t position, const void *elt)
391 size_t count = (list->root != NULL ? list->root->branch_size : 0);
393 if (!(position <= count))
394 /* Invalid argument. */
396 if (position == count)
397 return gl_tree_add_last (list, elt);
399 return gl_tree_add_before (list, node_at (list->root, position), elt);
403 gl_tree_remove_at (gl_list_t list, size_t position)
405 gl_list_node_t node = list->root;
407 if (!(node != NULL && position < node->branch_size))
408 /* Invalid argument. */
410 node = node_at (node, position);
411 return gl_tree_remove_node (list, node);
415 gl_tree_remove (gl_list_t list, const void *elt)
417 if (list->root != NULL)
419 gl_list_node_t node =
420 gl_tree_search_from_to (list, 0, list->root->branch_size, elt);
423 return gl_tree_remove_node (list, node);
431 gl_tree_list_free (gl_list_t list)
433 /* Iterate across all elements in post-order. */
434 gl_list_node_t node = list->root;
436 iterstack_item_t *stack_ptr = &stack[0];
440 /* Descend on left branch. */
445 stack_ptr->node = node;
446 stack_ptr->rightp = false;
450 /* Climb up again. */
453 if (stack_ptr == &stack[0])
456 node = stack_ptr->node;
457 if (!stack_ptr->rightp)
459 /* Free the current node. */
462 /* Descend on right branch. */
463 stack_ptr->rightp = true;
473 /* --------------------- gl_list_iterator_t Data Type --------------------- */
475 static gl_list_iterator_t
476 gl_tree_iterator (gl_list_t list)
478 gl_list_iterator_t result;
481 result.vtable = list->base.vtable;
483 /* Start node is the leftmost node. */
486 while (node->left != NULL)
489 /* End point is past the rightmost node. */
500 static gl_list_iterator_t
501 gl_tree_iterator_from_to (gl_list_t list, size_t start_index, size_t end_index)
503 size_t count = (list->root != NULL ? list->root->branch_size : 0);
504 gl_list_iterator_t result;
506 if (!(start_index <= end_index && end_index <= count))
507 /* Invalid arguments. */
509 result.vtable = list->base.vtable;
511 /* Start node is the node at position start_index. */
512 result.p = (start_index < count ? node_at (list->root, start_index) : NULL);
513 /* End point is the node at position end_index. */
514 result.q = (end_index < count ? node_at (list->root, end_index) : NULL);
525 gl_tree_iterator_next (gl_list_iterator_t *iterator,
526 const void **eltp, gl_list_node_t *nodep)
528 if (iterator->p != iterator->q)
530 gl_list_node_t node = (gl_list_node_t) iterator->p;
534 /* Advance to the next node. */
535 if (node->right != NULL)
538 while (node->left != NULL)
543 while (node->parent != NULL && node->parent->right == node)
555 gl_tree_iterator_free (gl_list_iterator_t *iterator)
559 /* ---------------------- Sorted gl_list_t Data Type ---------------------- */
561 static gl_list_node_t
562 gl_tree_sortedlist_search (gl_list_t list, gl_listelement_compar_fn compar,
567 for (node = list->root; node != NULL; )
569 int cmp = compar (node->value, elt);
577 /* We have an element equal to ELT. But we need the leftmost such
579 gl_list_node_t found = node;
581 for (; node != NULL; )
583 int cmp2 = compar (node->value, elt);
588 /* The list was not sorted. */
602 static gl_list_node_t
603 gl_tree_sortedlist_search_from_to (gl_list_t list,
604 gl_listelement_compar_fn compar,
605 size_t low, size_t high,
611 && high <= (list->root != NULL ? list->root->branch_size : 0)))
612 /* Invalid arguments. */
615 for (node = list->root; node != NULL; )
617 size_t left_branch_size =
618 (node->left != NULL ? node->left->branch_size : 0);
620 if (low > left_branch_size)
622 low -= left_branch_size + 1;
623 high -= left_branch_size + 1;
626 else if (high <= left_branch_size)
630 /* Here low <= left_branch_size < high. */
631 int cmp = compar (node->value, elt);
636 high -= left_branch_size + 1;
643 /* We have an element equal to ELT. But we need the leftmost
645 gl_list_node_t found = node;
647 for (; node != NULL; )
649 size_t left_branch_size2 =
650 (node->left != NULL ? node->left->branch_size : 0);
652 if (low > left_branch_size2)
654 low -= left_branch_size2 + 1;
659 /* Here low <= left_branch_size2. */
660 int cmp2 = compar (node->value, elt);
668 /* The list was not sorted. */
685 gl_tree_sortedlist_indexof (gl_list_t list, gl_listelement_compar_fn compar,
691 for (node = list->root, position = 0; node != NULL; )
693 int cmp = compar (node->value, elt);
697 if (node->left != NULL)
698 position += node->left->branch_size;
706 /* We have an element equal to ELT. But we need the leftmost such
708 size_t found_position =
709 position + (node->left != NULL ? node->left->branch_size : 0);
711 for (; node != NULL; )
713 int cmp2 = compar (node->value, elt);
717 if (node->left != NULL)
718 position += node->left->branch_size;
723 /* The list was not sorted. */
729 + (node->left != NULL ? node->left->branch_size : 0);
733 return found_position;
740 gl_tree_sortedlist_indexof_from_to (gl_list_t list,
741 gl_listelement_compar_fn compar,
742 size_t low, size_t high,
749 && high <= (list->root != NULL ? list->root->branch_size : 0)))
750 /* Invalid arguments. */
753 for (node = list->root, position = 0; node != NULL; )
755 size_t left_branch_size =
756 (node->left != NULL ? node->left->branch_size : 0);
758 if (low > left_branch_size)
760 low -= left_branch_size + 1;
761 high -= left_branch_size + 1;
762 position += left_branch_size + 1;
765 else if (high <= left_branch_size)
769 /* Here low <= left_branch_size < high. */
770 int cmp = compar (node->value, elt);
775 high -= left_branch_size + 1;
776 position += left_branch_size + 1;
783 /* We have an element equal to ELT. But we need the leftmost
785 size_t found_position =
786 position + (node->left != NULL ? node->left->branch_size : 0);
788 for (; node != NULL; )
790 size_t left_branch_size2 =
791 (node->left != NULL ? node->left->branch_size : 0);
793 if (low > left_branch_size2)
795 low -= left_branch_size2 + 1;
800 /* Here low <= left_branch_size2. */
801 int cmp2 = compar (node->value, elt);
805 position += left_branch_size2 + 1;
809 /* The list was not sorted. */
813 found_position = position + left_branch_size2;
818 return found_position;
825 static gl_list_node_t
826 gl_tree_sortedlist_add (gl_list_t list, gl_listelement_compar_fn compar,
829 gl_list_node_t node = list->root;
832 return gl_tree_add_first (list, elt);
836 int cmp = compar (node->value, elt);
840 if (node->right == NULL)
841 return gl_tree_add_after (list, node, elt);
846 if (node->left == NULL)
847 return gl_tree_add_before (list, node, elt);
851 return gl_tree_add_before (list, node, elt);
856 gl_tree_sortedlist_remove (gl_list_t list, gl_listelement_compar_fn compar,
859 gl_list_node_t node = gl_tree_sortedlist_search (list, compar, elt);
861 return gl_tree_remove_node (list, node);