1 @node Container data types
2 @section Container data types
4 @c Copyright (C) 2019--2025 Free Software Foundation, Inc.
6 @c Permission is granted to copy, distribute and/or modify this document
7 @c under the terms of the GNU Free Documentation License, Version 1.3 or
8 @c any later version published by the Free Software Foundation; with no
9 @c Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A
10 @c copy of the license is at <https://www.gnu.org/licenses/fdl-1.3.en.html>.
12 @c Written by Bruno Haible.
14 @c This macro expands to \log in TeX mode, but just 'log' in HTML and info
22 @c This macro expands to \mathopsup in TeX mode, to a superscript in HTML
23 @c mode, and to ^ without braces in info mode.
25 @macro mathopsup {EXP}
30 @macro mathopsup {EXP}
35 Gnulib provides several generic container data types. They can be used
36 to organize collections of application-defined objects.
38 @node Ordinary containers
39 @subsection Ordinary container data types
48 @multitable @columnfractions .15 .45 .09 .15 .16
51 @multitable @columnfractions .15 .5 .1 .1 .15
56 @tab Main include file
57 @tab Include file for operations with out-of-memory checking
59 @tab Can contain any number of objects in any given order.
60 Duplicates are allowed, but can optionally be forbidden.
62 @tab @code{"gl_list.h"}
63 @tab @code{"gl_xlist.h"}
65 @tab Can contain any number of objects; the order does not matter.
66 Duplicates (in the sense of the comparator) are forbidden.
68 @tab @code{"gl_set.h"}
69 @tab @code{"gl_xset.h"}
71 @tab Can contain any number of objects in the order of a given comparator
73 Duplicates (in the sense of the comparator) are forbidden.
75 @tab @code{"gl_oset.h"}
76 @tab @code{"gl_xoset.h"}
78 @tab Can contain any number of (key, value) pairs, where keys and values
80 there are no (key, value1) and (key, value2) pairs with the same key
81 (in the sense of a given comparator function).
83 @tab @code{"gl_map.h"}
84 @tab @code{"gl_xmap.h"}
86 @tab Can contain any number of (key, value) pairs, where keys and values
88 the (key, value) pairs are ordered by the key, in the order of a given
90 there are no (key, value1) and (key, value2) pairs with the same key
91 (in the sense of the comparator function).
93 @tab @code{"gl_omap.h"}
94 @tab @code{"gl_xomap.h"}
97 Operations without out-of-memory checking (suitable for use in libraries) are
98 declared in the ``main include file''. Whereas operations with out-of-memory
99 checking (suitable only in programs) are declared in the ``include file for
100 operations with out-of-memory checking''.
102 For each of the data types, several implementations are available, with
103 different performance profiles with respect to the available operations.
104 This enables you to start with the simplest implementation (ARRAY) initially,
105 and switch to a more suitable implementation after profiling your application.
106 The implementation of each container instance is specified in a single place
107 only: in the invocation of the function @code{gl_*_create_empty} that creates
110 @subsubsection Sequential lists
112 The implementations and the guaranteed average performance for the operations
113 for the ``sequential list'' data type are:
117 Note: This table is overloaded in the @command{info}-formatted documentation.
118 It is better viewable in the HTML-formatted documentation.
121 @multitable @columnfractions 0.2 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1
127 @tab LINKEDHASH with duplicates
128 @tab LINKEDHASH without duplicates
129 @tab TREEHASH with duplicates
130 @tab TREEHASH without duplicates
131 @item @code{gl_list_size}
140 @item @code{gl_list_node_value}
149 @item @code{gl_list_node_set_value}
156 @tab @math{O((@log n)@mathopsup{2})}
158 @item @code{gl_list_next_node}
162 @tab @math{O(@log n)}
165 @tab @math{O(@log n)}
166 @tab @math{O(@log n)}
167 @item @code{gl_list_previous_node}
171 @tab @math{O(@log n)}
174 @tab @math{O(@log n)}
175 @tab @math{O(@log n)}
176 @item @code{gl_list_first_node}
180 @tab @math{O(@log n)}
183 @tab @math{O(@log n)}
184 @tab @math{O(@log n)}
185 @item @code{gl_list_last_node}
189 @tab @math{O(@log n)}
192 @tab @math{O(@log n)}
193 @tab @math{O(@log n)}
194 @item @code{gl_list_get_at}
198 @tab @math{O(@log n)}
201 @tab @math{O(@log n)}
202 @tab @math{O(@log n)}
203 @item @code{gl_list_get_first}
207 @tab @math{O(@log n)}
210 @tab @math{O(@log n)}
211 @tab @math{O(@log n)}
212 @item @code{gl_list_get_last}
216 @tab @math{O(@log n)}
219 @tab @math{O(@log n)}
220 @tab @math{O(@log n)}
221 @item @code{gl_list_set_at}
225 @tab @math{O(@log n)}
228 @tab @math{O((@log n)@mathopsup{2})}
229 @tab @math{O(@log n)}
230 @item @code{gl_list_set_first}
234 @tab @math{O(@log n)}
237 @tab @math{O((@log n)@mathopsup{2})}
238 @tab @math{O(@log n)}
239 @item @code{gl_list_set_last}
243 @tab @math{O(@log n)}
246 @tab @math{O((@log n)@mathopsup{2})}
247 @tab @math{O(@log n)}
248 @item @code{gl_list_search}
255 @tab @math{O(@log n)}
257 @item @code{gl_list_search_from}
264 @tab @math{O((@log n)@mathopsup{2})}
265 @tab @math{O(@log n)}
266 @item @code{gl_list_search_from_to}
273 @tab @math{O((@log n)@mathopsup{2})}
274 @tab @math{O(@log n)}
275 @item @code{gl_list_indexof}
282 @tab @math{O(@log n)}
283 @tab @math{O(@log n)}
284 @item @code{gl_list_indexof_from}
291 @tab @math{O((@log n)@mathopsup{2})}
292 @tab @math{O(@log n)}
293 @item @code{gl_list_indexof_from_to}
300 @tab @math{O((@log n)@mathopsup{2})}
301 @tab @math{O(@log n)}
302 @item @code{gl_list_add_first}
306 @tab @math{O(@log n)}
309 @tab @math{O((@log n)@mathopsup{2})}
310 @tab @math{O(@log n)}
311 @item @code{gl_list_add_last}
315 @tab @math{O(@log n)}
318 @tab @math{O((@log n)@mathopsup{2})}
319 @tab @math{O(@log n)}
320 @item @code{gl_list_add_before}
324 @tab @math{O(@log n)}
327 @tab @math{O((@log n)@mathopsup{2})}
328 @tab @math{O(@log n)}
329 @item @code{gl_list_add_after}
333 @tab @math{O(@log n)}
336 @tab @math{O((@log n)@mathopsup{2})}
337 @tab @math{O(@log n)}
338 @item @code{gl_list_add_at}
342 @tab @math{O(@log n)}
345 @tab @math{O((@log n)@mathopsup{2})}
346 @tab @math{O(@log n)}
347 @item @code{gl_list_remove_node}
351 @tab @math{O(@log n)}
354 @tab @math{O((@log n)@mathopsup{2})}
355 @tab @math{O(@log n)}
356 @item @code{gl_list_remove_at}
360 @tab @math{O(@log n)}
363 @tab @math{O((@log n)@mathopsup{2})}
364 @tab @math{O(@log n)}
365 @item @code{gl_list_remove_first}
369 @tab @math{O(@log n)}
372 @tab @math{O((@log n)@mathopsup{2})}
373 @tab @math{O(@log n)}
374 @item @code{gl_list_remove_last}
378 @tab @math{O(@log n)}
381 @tab @math{O((@log n)@mathopsup{2})}
382 @tab @math{O(@log n)}
383 @item @code{gl_list_remove}
390 @tab @math{O((@log n)@mathopsup{2})}
391 @tab @math{O(@log n)}
392 @item @code{gl_list_iterator}
396 @tab @math{O(@log n)}
399 @tab @math{O(@log n)}
400 @tab @math{O(@log n)}
401 @item @code{gl_list_iterator_from_to}
405 @tab @math{O(@log n)}
408 @tab @math{O(@log n)}
409 @tab @math{O(@log n)}
410 @item @code{gl_list_iterator_next}
414 @tab @math{O(@log n)}
417 @tab @math{O(@log n)}
418 @tab @math{O(@log n)}
419 @item @code{gl_sortedlist_search}
420 @tab @math{O(@log n)}
421 @tab @math{O(@log n)}
423 @tab @math{O(@log n)}
426 @tab @math{O(@log n)}
427 @tab @math{O(@log n)}
428 @item @code{gl_sortedlist_search_from}
429 @tab @math{O(@log n)}
430 @tab @math{O(@log n)}
432 @tab @math{O(@log n)}
435 @tab @math{O(@log n)}
436 @tab @math{O(@log n)}
437 @item @code{gl_sortedlist_indexof}
438 @tab @math{O(@log n)}
439 @tab @math{O(@log n)}
441 @tab @math{O(@log n)}
444 @tab @math{O(@log n)}
445 @tab @math{O(@log n)}
446 @item @code{gl_sortedlist_indexof_from}
447 @tab @math{O(@log n)}
448 @tab @math{O(@log n)}
450 @tab @math{O(@log n)}
453 @tab @math{O(@log n)}
454 @tab @math{O(@log n)}
455 @item @code{gl_sortedlist_add}
459 @tab @math{O(@log n)}
462 @tab @math{O((@log n)@mathopsup{2})}
463 @tab @math{O(@log n)}
464 @item @code{gl_sortedlist_remove}
468 @tab @math{O(@log n)}
471 @tab @math{O((@log n)@mathopsup{2})}
472 @tab @math{O(@log n)}
475 The Gnulib modules for sequential lists are:
484 @mindex linkedhash-list
485 @mindex avltreehash-list
486 @mindex rbtreehash-list
489 @multitable @columnfractions 0.3 0.7
490 @headitem Implementation @tab Modules
491 @item Abstract @tab @code{list}, @code{xlist}
492 @item ARRAY @tab @code{array-list}
493 @item CARRAY @tab @code{carray-list}
494 @item LINKED @tab @code{linked-list}
495 @item TREE @tab @code{avltree-list}, @code{rbtree-list}
496 @item LINKEDHASH @tab @code{linkedhash-list}
497 @item TREEHASH @tab @code{avltreehash-list}, @code{rbtreehash-list}
498 @item Portion of a list @tab @code{sublist}, @code{xsublist}
503 The implementations and the guaranteed average performance for the operations
504 for the ``set'' data type are:
506 @multitable @columnfractions 0.4 0.2 0.4
509 @tab LINKEDHASH, HASH
510 @item @code{gl_set_size}
513 @item @code{gl_set_add}
516 @item @code{gl_set_remove}
519 @item @code{gl_set_search}
522 @item @code{gl_set_iterator}
525 @item @code{gl_set_iterator_next}
530 The Gnulib modules for sets are:
535 @mindex linkedhash-set
537 @multitable @columnfractions 0.3 0.7
538 @headitem Implementation @tab Modules
539 @item Abstract @tab @code{set}, @code{xset}
540 @item ARRAY @tab @code{array-set}
541 @item LINKEDHASH @tab @code{linkedhash-set}
542 @item HASH @tab @code{hash-set}
545 @subsubsection Ordered sets
547 The implementations and the guaranteed average performance for the operations
548 for the ``ordered set'' data type are:
550 @multitable @columnfractions 0.5 0.25 0.25
554 @item @code{gl_oset_size}
557 @item @code{gl_oset_add}
559 @tab @math{O(@log n)}
560 @item @code{gl_oset_remove}
562 @tab @math{O(@log n)}
563 @item @code{gl_oset_search}
564 @tab @math{O(@log n)}
565 @tab @math{O(@log n)}
566 @item @code{gl_oset_search_atleast}
567 @tab @math{O(@log n)}
568 @tab @math{O(@log n)}
569 @item @code{gl_oset_iterator}
571 @tab @math{O(@log n)}
572 @item @code{gl_oset_iterator_next}
574 @tab @math{O(@log n)}
577 The Gnulib modules for ordered sets are:
584 @multitable @columnfractions 0.3 0.7
585 @headitem Implementation @tab Modules
586 @item Abstract @tab @code{oset}, @code{xoset}
587 @item ARRAY @tab @code{array-oset}
588 @item TREE @tab @code{avltree-oset}, @code{rbtree-oset}
593 The implementations and the guaranteed average performance for the operations
594 for the ``map'' data type are:
596 @multitable @columnfractions 0.4 0.2 0.4
599 @tab LINKEDHASH, HASH
600 @item @code{gl_map_size}
603 @item @code{gl_map_get}
606 @item @code{gl_map_put}
609 @item @code{gl_map_remove}
612 @item @code{gl_map_search}
615 @item @code{gl_map_iterator}
618 @item @code{gl_map_iterator_next}
623 The Gnulib modules for maps are:
628 @mindex linkedhash-map
630 @multitable @columnfractions 0.3 0.7
631 @headitem Implementation @tab Modules
632 @item Abstract @tab @code{map}, @code{xmap}
633 @item ARRAY @tab @code{array-map}
634 @item LINKEDHASH @tab @code{linkedhash-map}
635 @item HASH @tab @code{hash-map}
638 @subsubsection Ordered maps
640 The implementations and the guaranteed average performance for the operations
641 for the ``ordered map'' data type are:
643 @multitable @columnfractions 0.5 0.25 0.25
647 @item @code{gl_omap_size}
650 @item @code{gl_omap_get}
651 @tab @math{O(@log n)}
652 @tab @math{O(@log n)}
653 @item @code{gl_omap_put}
655 @tab @math{O(@log n)}
656 @item @code{gl_omap_remove}
658 @tab @math{O(@log n)}
659 @item @code{gl_omap_search}
660 @tab @math{O(@log n)}
661 @tab @math{O(@log n)}
662 @item @code{gl_omap_search_atleast}
663 @tab @math{O(@log n)}
664 @tab @math{O(@log n)}
665 @item @code{gl_omap_iterator}
667 @tab @math{O(@log n)}
668 @item @code{gl_omap_iterator_next}
670 @tab @math{O(@log n)}
673 The Gnulib modules for ordered maps are:
680 @multitable @columnfractions 0.3 0.7
681 @headitem Implementation @tab Modules
682 @item Abstract @tab @code{omap}, @code{xomap}
683 @item ARRAY @tab @code{array-omap}
684 @item TREE @tab @code{avltree-omap}, @code{rbtree-omap}
687 @subsubsection C++ classes for container data types
689 For C++, Gnulib provides a C++ template class for each of these container data types.
696 @multitable @columnfractions .30 .20 .25 .25
701 @item Sequential list
704 @tab @code{"gl_list.hh"}
708 @tab @code{"gl_set.hh"}
712 @tab @code{"gl_oset.hh"}
716 @tab @code{"gl_map.hh"}
720 @tab @code{"gl_omap.hh"}
723 @node Specialized containers
724 @subsection Specialized container data types
727 The @code{hamt} module implements the hash array mapped trie (HAMT) data
728 structure. This is a data structure that contains (key, value) pairs.
729 Lookup of a (key, value) pair given the key is on average an @math{O(1)}
730 operation, assuming a good hash function for the keys is employed.
732 The HAMT data structure is useful when you want modifications (additions
733 of pairs, removal, value changes) to be visible only to some part of
734 your program, whereas other parts of the program continue to use the
735 unmodified HAMT. The HAMT makes this possible in a space-efficient
736 manner: the modified and the unmodified HAMT share most of their
737 allocated memory. It is also time-efficient: Every such modification
738 is @math{O(1)} on average, again assuming a good hash function for the keys.
740 A HAMT can be used whenever an ordinary hash table would be used. It
741 does however, provide non-destructive updating operations without the
742 need to copy the whole container. On the other hand, a hash table is
743 simpler so that its performance may be better when non-destructive
744 update operations are not needed.
746 For example, a HAMT can be used to model the dynamic environment in a
747 LISP interpreter. Updating a value in the dynamic environment of one
748 continuation frame would not modify values in earlier frames.
750 To use the module, include @code{hamt.h} in your code. The public
751 interface is documented in that header file. You have to provide a hash
752 function and an equivalence relation, which defines key equality. The
753 module includes a test file @code{test-hamt.c}, which demonstrates how
756 In the current implementation, each inner node of the HAMT can store up
757 to @math{32 = 2^5} entries and subtries. Whenever a collision between
758 the initial bits of the hash values of two entries would happen, the
759 next @math{5} bits of the hash values are examined and the two entries
760 pushed down one level in the trie.
762 HAMTs have the same average access times as hash tables but grow and
763 shrink dynamically, so they use memory more economically and do not have
764 to be periodically resized.
766 They were described and analyzed in @cite{Phil Bagwell (2000). Ideal
767 Hash Trees (Report). Infoscience Department, École Polytechnique
768 Fédérale de Lausanne.}
770 The persistence aspect of the HAMT data structure, which means that each
771 updating operation (like inserting, replacing, or removing an entry)
772 returns a new HAMT while leaving the original one intact, is achieved
773 through structure sharing, which is even safe in the presence of
774 multiple threads when the used C compiler supports atomics.