| @node Container data types | |
| @section Container data types | |
| @c Copyright (C) 2019--2026 Free Software Foundation, Inc. | |
| @c Permission is granted to copy, distribute and/or modify this document | |
| @c under the terms of the GNU Free Documentation License, Version 1.3 or | |
| @c any later version published by the Free Software Foundation; with no | |
| @c Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A | |
| @c copy of the license is at <https://www.gnu.org/licenses/fdl-1.3.en.html>. | |
| @c Written by Bruno Haible. | |
| @c This macro expands to \log in TeX mode, but just 'log' in HTML and info | |
| @c modes. | |
| @ifnottex | |
| @macro log | |
| log | |
| @end macro | |
| @end ifnottex | |
| @c This macro expands to \mathopsup in TeX mode, to a superscript in HTML | |
| @c mode, and to ^ without braces in info mode. | |
| @ifhtml | |
| @macro mathopsup {EXP} | |
| @sup{\EXP\} | |
| @end macro | |
| @end ifhtml | |
| @ifinfo | |
| @macro mathopsup {EXP} | |
| ^\EXP\ | |
| @end macro | |
| @end ifinfo | |
| Gnulib provides several generic container data types. They can be used | |
| to organize collections of application-defined objects. | |
| @node Ordinary containers | |
| @subsection Ordinary container data types | |
| @mindex list | |
| @mindex set | |
| @mindex oset | |
| @mindex map | |
| @mindex omap | |
| @ifinfo | |
| @multitable @columnfractions .15 .45 .09 .15 .16 | |
| @end ifinfo | |
| @ifnotinfo | |
| @multitable @columnfractions .15 .5 .1 .1 .15 | |
| @end ifnotinfo | |
| @headitem Data type | |
| @tab Details | |
| @tab Module | |
| @tab Main include file | |
| @tab Include file for operations with out-of-memory checking | |
| @item Sequential list | |
| @tab Can contain any number of objects in any given order. | |
| Duplicates are allowed, but can optionally be forbidden. | |
| @tab @code{list} | |
| @tab @code{"gl_list.h"} | |
| @tab @code{"gl_xlist.h"} | |
| @item Set | |
| @tab Can contain any number of objects; the order does not matter. | |
| Duplicates (in the sense of the comparator) are forbidden. | |
| @tab @code{set} | |
| @tab @code{"gl_set.h"} | |
| @tab @code{"gl_xset.h"} | |
| @item Ordered set | |
| @tab Can contain any number of objects in the order of a given comparator | |
| function. | |
| Duplicates (in the sense of the comparator) are forbidden. | |
| @tab @code{oset} | |
| @tab @code{"gl_oset.h"} | |
| @tab @code{"gl_xoset.h"} | |
| @item Map | |
| @tab Can contain any number of (key, value) pairs, where keys and values | |
| are objects; | |
| there are no (key, value1) and (key, value2) pairs with the same key | |
| (in the sense of a given comparator function). | |
| @tab @code{map} | |
| @tab @code{"gl_map.h"} | |
| @tab @code{"gl_xmap.h"} | |
| @item Ordered map | |
| @tab Can contain any number of (key, value) pairs, where keys and values | |
| are objects; | |
| the (key, value) pairs are ordered by the key, in the order of a given | |
| comparator function; | |
| there are no (key, value1) and (key, value2) pairs with the same key | |
| (in the sense of the comparator function). | |
| @tab @code{omap} | |
| @tab @code{"gl_omap.h"} | |
| @tab @code{"gl_xomap.h"} | |
| @end multitable | |
| Operations without out-of-memory checking (suitable for use in libraries) are | |
| declared in the ``main include file''. Whereas operations with out-of-memory | |
| checking (suitable only in programs) are declared in the ``include file for | |
| operations with out-of-memory checking''. | |
| For each of the data types, several implementations are available, with | |
| different performance profiles with respect to the available operations. | |
| This enables you to start with the simplest implementation (ARRAY) initially, | |
| and switch to a more suitable implementation after profiling your application. | |
| The implementation of each container instance is specified in a single place | |
| only: in the invocation of the function @code{gl_*_create_empty} that creates | |
| the instance. | |
| @subsubsection Sequential lists | |
| The implementations and the guaranteed average performance for the operations | |
| for the ``sequential list'' data type are: | |
| @ifinfo | |
| @noindent | |
| Note: This table is overloaded in the @command{info}-formatted documentation. | |
| It is better viewable in the HTML-formatted documentation. | |
| @end ifinfo | |
| @multitable @columnfractions 0.2 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 | |
| @headitem Operation | |
| @tab ARRAY | |
| @tab CARRAY | |
| @tab LINKED | |
| @tab TREE | |
| @tab LINKEDHASH with duplicates | |
| @tab LINKEDHASH without duplicates | |
| @tab TREEHASH with duplicates | |
| @tab TREEHASH without duplicates | |
| @item @code{gl_list_size} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @item @code{gl_list_node_value} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @item @code{gl_list_node_set_value} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @tab @math{O((@log n)@mathopsup{2})} | |
| @tab @math{O(1)} | |
| @item @code{gl_list_next_node} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @tab @math{O(@log n)} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @tab @math{O(@log n)} | |
| @tab @math{O(@log n)} | |
| @item @code{gl_list_previous_node} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @tab @math{O(@log n)} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @tab @math{O(@log n)} | |
| @tab @math{O(@log n)} | |
| @item @code{gl_list_first_node} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @tab @math{O(@log n)} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @tab @math{O(@log n)} | |
| @tab @math{O(@log n)} | |
| @item @code{gl_list_last_node} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @tab @math{O(@log n)} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @tab @math{O(@log n)} | |
| @tab @math{O(@log n)} | |
| @item @code{gl_list_get_at} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @tab @math{O(n)} | |
| @tab @math{O(@log n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(@log n)} | |
| @tab @math{O(@log n)} | |
| @item @code{gl_list_get_first} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @tab @math{O(@log n)} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @tab @math{O(@log n)} | |
| @tab @math{O(@log n)} | |
| @item @code{gl_list_get_last} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @tab @math{O(@log n)} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @tab @math{O(@log n)} | |
| @tab @math{O(@log n)} | |
| @item @code{gl_list_set_at} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @tab @math{O(n)} | |
| @tab @math{O(@log n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(n)} | |
| @tab @math{O((@log n)@mathopsup{2})} | |
| @tab @math{O(@log n)} | |
| @item @code{gl_list_set_first} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @tab @math{O(@log n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(1)} | |
| @tab @math{O((@log n)@mathopsup{2})} | |
| @tab @math{O(@log n)} | |
| @item @code{gl_list_set_last} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @tab @math{O(@log n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(1)} | |
| @tab @math{O((@log n)@mathopsup{2})} | |
| @tab @math{O(@log n)} | |
| @item @code{gl_list_search} | |
| @tab @math{O(n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(1)} | |
| @tab @math{O(@log n)} | |
| @tab @math{O(1)} | |
| @item @code{gl_list_search_from} | |
| @tab @math{O(n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(1)} | |
| @tab @math{O((@log n)@mathopsup{2})} | |
| @tab @math{O(@log n)} | |
| @item @code{gl_list_search_from_to} | |
| @tab @math{O(n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(1)} | |
| @tab @math{O((@log n)@mathopsup{2})} | |
| @tab @math{O(@log n)} | |
| @item @code{gl_list_indexof} | |
| @tab @math{O(n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(@log n)} | |
| @tab @math{O(@log n)} | |
| @item @code{gl_list_indexof_from} | |
| @tab @math{O(n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(n)} | |
| @tab @math{O((@log n)@mathopsup{2})} | |
| @tab @math{O(@log n)} | |
| @item @code{gl_list_indexof_from_to} | |
| @tab @math{O(n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(n)} | |
| @tab @math{O((@log n)@mathopsup{2})} | |
| @tab @math{O(@log n)} | |
| @item @code{gl_list_add_first} | |
| @tab @math{O(n)} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @tab @math{O(@log n)} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @tab @math{O((@log n)@mathopsup{2})} | |
| @tab @math{O(@log n)} | |
| @item @code{gl_list_add_last} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @tab @math{O(@log n)} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @tab @math{O((@log n)@mathopsup{2})} | |
| @tab @math{O(@log n)} | |
| @item @code{gl_list_add_before} | |
| @tab @math{O(n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(1)} | |
| @tab @math{O(@log n)} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @tab @math{O((@log n)@mathopsup{2})} | |
| @tab @math{O(@log n)} | |
| @item @code{gl_list_add_after} | |
| @tab @math{O(n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(1)} | |
| @tab @math{O(@log n)} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @tab @math{O((@log n)@mathopsup{2})} | |
| @tab @math{O(@log n)} | |
| @item @code{gl_list_add_at} | |
| @tab @math{O(n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(@log n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(n)} | |
| @tab @math{O((@log n)@mathopsup{2})} | |
| @tab @math{O(@log n)} | |
| @item @code{gl_list_remove_node} | |
| @tab @math{O(n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(1)} | |
| @tab @math{O(@log n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(1)} | |
| @tab @math{O((@log n)@mathopsup{2})} | |
| @tab @math{O(@log n)} | |
| @item @code{gl_list_remove_at} | |
| @tab @math{O(n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(@log n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(n)} | |
| @tab @math{O((@log n)@mathopsup{2})} | |
| @tab @math{O(@log n)} | |
| @item @code{gl_list_remove_first} | |
| @tab @math{O(n)} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @tab @math{O(@log n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(1)} | |
| @tab @math{O((@log n)@mathopsup{2})} | |
| @tab @math{O(@log n)} | |
| @item @code{gl_list_remove_last} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @tab @math{O(@log n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(1)} | |
| @tab @math{O((@log n)@mathopsup{2})} | |
| @tab @math{O(@log n)} | |
| @item @code{gl_list_remove} | |
| @tab @math{O(n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(1)} | |
| @tab @math{O((@log n)@mathopsup{2})} | |
| @tab @math{O(@log n)} | |
| @item @code{gl_list_iterator} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @tab @math{O(@log n)} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @tab @math{O(@log n)} | |
| @tab @math{O(@log n)} | |
| @item @code{gl_list_iterator_from_to} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @tab @math{O(n)} | |
| @tab @math{O(@log n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(@log n)} | |
| @tab @math{O(@log n)} | |
| @item @code{gl_list_iterator_next} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @tab @math{O(@log n)} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @tab @math{O(@log n)} | |
| @tab @math{O(@log n)} | |
| @item @code{gl_sortedlist_search} | |
| @tab @math{O(@log n)} | |
| @tab @math{O(@log n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(@log n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(@log n)} | |
| @tab @math{O(@log n)} | |
| @item @code{gl_sortedlist_search_from} | |
| @tab @math{O(@log n)} | |
| @tab @math{O(@log n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(@log n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(@log n)} | |
| @tab @math{O(@log n)} | |
| @item @code{gl_sortedlist_indexof} | |
| @tab @math{O(@log n)} | |
| @tab @math{O(@log n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(@log n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(@log n)} | |
| @tab @math{O(@log n)} | |
| @item @code{gl_sortedlist_indexof_from} | |
| @tab @math{O(@log n)} | |
| @tab @math{O(@log n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(@log n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(@log n)} | |
| @tab @math{O(@log n)} | |
| @item @code{gl_sortedlist_add} | |
| @tab @math{O(n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(@log n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(n)} | |
| @tab @math{O((@log n)@mathopsup{2})} | |
| @tab @math{O(@log n)} | |
| @item @code{gl_sortedlist_remove} | |
| @tab @math{O(n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(@log n)} | |
| @tab @math{O(n)} | |
| @tab @math{O(n)} | |
| @tab @math{O((@log n)@mathopsup{2})} | |
| @tab @math{O(@log n)} | |
| @end multitable | |
| The Gnulib modules for sequential lists are: | |
| @mindex list | |
| @mindex xlist | |
| @mindex array-list | |
| @mindex carray-list | |
| @mindex linked-list | |
| @mindex avltree-list | |
| @mindex rbtree-list | |
| @mindex linkedhash-list | |
| @mindex avltreehash-list | |
| @mindex rbtreehash-list | |
| @mindex sublist | |
| @mindex xsublist | |
| @multitable @columnfractions 0.3 0.7 | |
| @headitem Implementation @tab Modules | |
| @item Abstract @tab @code{list}, @code{xlist} | |
| @item ARRAY @tab @code{array-list} | |
| @item CARRAY @tab @code{carray-list} | |
| @item LINKED @tab @code{linked-list} | |
| @item TREE @tab @code{avltree-list}, @code{rbtree-list} | |
| @item LINKEDHASH @tab @code{linkedhash-list} | |
| @item TREEHASH @tab @code{avltreehash-list}, @code{rbtreehash-list} | |
| @item Portion of a list @tab @code{sublist}, @code{xsublist} | |
| @end multitable | |
| @subsubsection Sets | |
| The implementations and the guaranteed average performance for the operations | |
| for the ``set'' data type are: | |
| @multitable @columnfractions 0.4 0.2 0.4 | |
| @headitem Operation | |
| @tab ARRAY | |
| @tab LINKEDHASH, HASH | |
| @item @code{gl_set_size} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @item @code{gl_set_add} | |
| @tab @math{O(n)} | |
| @tab @math{O(1)} | |
| @item @code{gl_set_remove} | |
| @tab @math{O(n)} | |
| @tab @math{O(1)} | |
| @item @code{gl_set_search} | |
| @tab @math{O(n)} | |
| @tab @math{O(1)} | |
| @item @code{gl_set_iterator} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @item @code{gl_set_iterator_next} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @end multitable | |
| The Gnulib modules for sets are: | |
| @mindex set | |
| @mindex xset | |
| @mindex array-set | |
| @mindex linkedhash-set | |
| @mindex hash-set | |
| @multitable @columnfractions 0.3 0.7 | |
| @headitem Implementation @tab Modules | |
| @item Abstract @tab @code{set}, @code{xset} | |
| @item ARRAY @tab @code{array-set} | |
| @item LINKEDHASH @tab @code{linkedhash-set} | |
| @item HASH @tab @code{hash-set} | |
| @end multitable | |
| @subsubsection Ordered sets | |
| The implementations and the guaranteed average performance for the operations | |
| for the ``ordered set'' data type are: | |
| @multitable @columnfractions 0.5 0.25 0.25 | |
| @headitem Operation | |
| @tab ARRAY | |
| @tab TREE | |
| @item @code{gl_oset_size} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @item @code{gl_oset_add} | |
| @tab @math{O(n)} | |
| @tab @math{O(@log n)} | |
| @item @code{gl_oset_remove} | |
| @tab @math{O(n)} | |
| @tab @math{O(@log n)} | |
| @item @code{gl_oset_search} | |
| @tab @math{O(@log n)} | |
| @tab @math{O(@log n)} | |
| @item @code{gl_oset_search_atleast} | |
| @tab @math{O(@log n)} | |
| @tab @math{O(@log n)} | |
| @item @code{gl_oset_iterator} | |
| @tab @math{O(1)} | |
| @tab @math{O(@log n)} | |
| @item @code{gl_oset_iterator_next} | |
| @tab @math{O(1)} | |
| @tab @math{O(@log n)} | |
| @end multitable | |
| The Gnulib modules for ordered sets are: | |
| @mindex oset | |
| @mindex xoset | |
| @mindex array-oset | |
| @mindex avltree-oset | |
| @mindex rbtree-oset | |
| @multitable @columnfractions 0.3 0.7 | |
| @headitem Implementation @tab Modules | |
| @item Abstract @tab @code{oset}, @code{xoset} | |
| @item ARRAY @tab @code{array-oset} | |
| @item TREE @tab @code{avltree-oset}, @code{rbtree-oset} | |
| @end multitable | |
| @subsubsection Maps | |
| The implementations and the guaranteed average performance for the operations | |
| for the ``map'' data type are: | |
| @multitable @columnfractions 0.4 0.2 0.4 | |
| @headitem Operation | |
| @tab ARRAY | |
| @tab LINKEDHASH, HASH | |
| @item @code{gl_map_size} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @item @code{gl_map_get} | |
| @tab @math{O(n)} | |
| @tab @math{O(1)} | |
| @item @code{gl_map_put} | |
| @tab @math{O(n)} | |
| @tab @math{O(1)} | |
| @item @code{gl_map_remove} | |
| @tab @math{O(n)} | |
| @tab @math{O(1)} | |
| @item @code{gl_map_search} | |
| @tab @math{O(n)} | |
| @tab @math{O(1)} | |
| @item @code{gl_map_iterator} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @item @code{gl_map_iterator_next} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @end multitable | |
| The Gnulib modules for maps are: | |
| @mindex map | |
| @mindex xmap | |
| @mindex array-map | |
| @mindex linkedhash-map | |
| @mindex hash-map | |
| @multitable @columnfractions 0.3 0.7 | |
| @headitem Implementation @tab Modules | |
| @item Abstract @tab @code{map}, @code{xmap} | |
| @item ARRAY @tab @code{array-map} | |
| @item LINKEDHASH @tab @code{linkedhash-map} | |
| @item HASH @tab @code{hash-map} | |
| @end multitable | |
| @subsubsection Ordered maps | |
| The implementations and the guaranteed average performance for the operations | |
| for the ``ordered map'' data type are: | |
| @multitable @columnfractions 0.5 0.25 0.25 | |
| @headitem Operation | |
| @tab ARRAY | |
| @tab TREE | |
| @item @code{gl_omap_size} | |
| @tab @math{O(1)} | |
| @tab @math{O(1)} | |
| @item @code{gl_omap_get} | |
| @tab @math{O(@log n)} | |
| @tab @math{O(@log n)} | |
| @item @code{gl_omap_put} | |
| @tab @math{O(n)} | |
| @tab @math{O(@log n)} | |
| @item @code{gl_omap_remove} | |
| @tab @math{O(n)} | |
| @tab @math{O(@log n)} | |
| @item @code{gl_omap_search} | |
| @tab @math{O(@log n)} | |
| @tab @math{O(@log n)} | |
| @item @code{gl_omap_search_atleast} | |
| @tab @math{O(@log n)} | |
| @tab @math{O(@log n)} | |
| @item @code{gl_omap_iterator} | |
| @tab @math{O(1)} | |
| @tab @math{O(@log n)} | |
| @item @code{gl_omap_iterator_next} | |
| @tab @math{O(1)} | |
| @tab @math{O(@log n)} | |
| @end multitable | |
| The Gnulib modules for ordered maps are: | |
| @mindex omap | |
| @mindex xomap | |
| @mindex array-omap | |
| @mindex avltree-omap | |
| @mindex rbtree-omap | |
| @multitable @columnfractions 0.3 0.7 | |
| @headitem Implementation @tab Modules | |
| @item Abstract @tab @code{omap}, @code{xomap} | |
| @item ARRAY @tab @code{array-omap} | |
| @item TREE @tab @code{avltree-omap}, @code{rbtree-omap} | |
| @end multitable | |
| @subsubsection C++ classes for container data types | |
| For C++, Gnulib provides a C++ template class for each of these container data types. | |
| @mindex list-c++ | |
| @mindex set-c++ | |
| @mindex oset-c++ | |
| @mindex map-c++ | |
| @mindex omap-c++ | |
| @multitable @columnfractions .30 .20 .25 .25 | |
| @headitem Data type | |
| @tab C++ class | |
| @tab Module | |
| @tab Include file | |
| @item Sequential list | |
| @tab @code{gl_List} | |
| @tab @code{list-c++} | |
| @tab @code{"gl_list.hh"} | |
| @item Set | |
| @tab @code{gl_Set} | |
| @tab @code{set-c++} | |
| @tab @code{"gl_set.hh"} | |
| @item Ordered set | |
| @tab @code{gl_OSet} | |
| @tab @code{oset-c++} | |
| @tab @code{"gl_oset.hh"} | |
| @item Map | |
| @tab @code{gl_Map} | |
| @tab @code{map-c++} | |
| @tab @code{"gl_map.hh"} | |
| @item Ordered map | |
| @tab @code{gl_OMap} | |
| @tab @code{omap-c++} | |
| @tab @code{"gl_omap.hh"} | |
| @end multitable | |
| @node Specialized containers | |
| @subsection Specialized container data types | |
| @mindex hamt | |
| The @code{hamt} module implements the hash array mapped trie (HAMT) data | |
| structure. This is a data structure that contains (key, value) pairs. | |
| Lookup of a (key, value) pair given the key is on average an @math{O(1)} | |
| operation, assuming a good hash function for the keys is employed. | |
| The HAMT data structure is useful when you want modifications (additions | |
| of pairs, removal, value changes) to be visible only to some part of | |
| your program, whereas other parts of the program continue to use the | |
| unmodified HAMT. The HAMT makes this possible in a space-efficient | |
| manner: the modified and the unmodified HAMT share most of their | |
| allocated memory. It is also time-efficient: Every such modification | |
| is @math{O(1)} on average, again assuming a good hash function for the keys. | |
| A HAMT can be used whenever an ordinary hash table would be used. It | |
| does however, provide non-destructive updating operations without the | |
| need to copy the whole container. On the other hand, a hash table is | |
| simpler so that its performance may be better when non-destructive | |
| update operations are not needed. | |
| For example, a HAMT can be used to model the dynamic environment in a | |
| LISP interpreter. Updating a value in the dynamic environment of one | |
| continuation frame would not modify values in earlier frames. | |
| To use the module, include @code{hamt.h} in your code. The public | |
| interface is documented in that header file. You have to provide a hash | |
| function and an equivalence relation, which defines key equality. The | |
| module includes a test file @code{test-hamt.c}, which demonstrates how | |
| the API can be used. | |
| In the current implementation, each inner node of the HAMT can store up | |
| to @math{32 = 2^5} entries and subtries. Whenever a collision between | |
| the initial bits of the hash values of two entries would happen, the | |
| next @math{5} bits of the hash values are examined and the two entries | |
| pushed down one level in the trie. | |
| HAMTs have the same average access times as hash tables but grow and | |
| shrink dynamically, so they use memory more economically and do not have | |
| to be periodically resized. | |
| They were described and analyzed in @cite{Phil Bagwell (2000). Ideal | |
| Hash Trees (Report). Infoscience Department, École Polytechnique | |
| Fédérale de Lausanne.} | |
| The persistence aspect of the HAMT data structure, which means that each | |
| updating operation (like inserting, replacing, or removing an entry) | |
| returns a new HAMT while leaving the original one intact, is achieved | |
| through structure sharing, which is even safe in the presence of | |
| multiple threads when the used C compiler supports atomics. | |
| @ifnottex | |
| @unmacro log | |
| @end ifnottex | |
| @ifhtml | |
| @unmacro mathopsup | |
| @end ifhtml | |
| @ifinfo | |
| @unmacro mathopsup | |
| @end ifinfo |