/****************************************************************************
 *   This file is part of the aGrUM/pyAgrum library.                        *
 *                                                                          *
 *   Copyright (c) 2005-2025 by                                             *
 *       - Pierre-Henri WUILLEMIN(_at_LIP6)                                 *
 *       - Christophe GONZALES(_at_AMU)                                     *
 *                                                                          *
 *   The aGrUM/pyAgrum library is free software; you can redistribute it    *
 *   and/or modify it under the terms of either :                           *
 *                                                                          *
 *    - the GNU Lesser General Public License as published by               *
 *      the Free Software Foundation, either version 3 of the License,      *
 *      or (at your option) any later version,                              *
 *    - the MIT license (MIT),                                              *
 *    - or both in dual license, as here.                                   *
 *                                                                          *
 *   (see https://agrum.gitlab.io/articles/dual-licenses-lgplv3mit.html)    *
 *                                                                          *
 *   This aGrUM/pyAgrum library is distributed in the hope that it will be  *
 *   useful, but WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,          *
 *   INCLUDING BUT NOT LIMITED TO THE WARRANTIES MERCHANTABILITY or FITNESS *
 *   FOR A PARTICULAR PURPOSE  AND NONINFRINGEMENT. IN NO EVENT SHALL THE   *
 *   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
 *   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,        *
 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR  *
 *   OTHER DEALINGS IN THE SOFTWARE.                                        *
 *                                                                          *
 *   See LICENCES for more details.                                         *
 *                                                                          *
 *   SPDX-FileCopyrightText: Copyright 2005-2025                            *
 *       - Pierre-Henri WUILLEMIN(_at_LIP6)                                 *
 *       - Christophe GONZALES(_at_AMU)                                     *
 *   SPDX-License-Identifier: LGPL-3.0-or-later OR MIT                      *
 *                                                                          *
 *   Contact  : info_at_agrum_dot_org                                       *
 *   homepage : http://agrum.gitlab.io                                      *
 *   gitlab   : https://gitlab.com/agrumery/agrum                           *
 *                                                                          *
 ****************************************************************************/


/**
 * @file
 * @brief Data structures documetnation.
 *
 * @author Pierre-Henri WUILLEMIN(@LIP6) & Christophe GONZALES(@AMU)
 * @author Lionel TORTI
 */

/**
 * \defgroup basicstruct_group Basic data structures
 * @{
 *
 * \defgroup hashtable_group Hash Tables
 * @{
 * \brief A efficient and flexible implementation of hash tables.
 *
 * This file provides class HashTable. This class is both efficient and
 * flexible: efficient because the access to elements is usually computed using
 * a small amount of processor instructions, and flexible because several
 * methods allow to fine tune the behavior of each hash table. For instance, a
 * hashtable can allow or forbid different elements to have the same key. This
 * behavior can be modified at any time during the execution of the program.
 * Functions for hashing keys are defined in file HashFunc.h. Here again, these
 * functions are quite flexible as they can be overloaded by the user to
 * support new kind of keys.  In addition to HashTable, the current file
 * provides classes HashTableIteratorSafe and HashTableConstIteratorSafe
 * (a.k.a.  HashTable<>::iterator_safe and HashTable<>::const_iterator_safe)
 * that allow safe parsing of the hash tables.  By safe, we mean that whenever
 * the element pointed to by such an iterator is removed from the hashtable,
 * accessing it through the iterator (*iter) does not result in a segmentation
 * fault but rather in an exception being thrown. This safety is ensured at a
 * very low cost (actually, our experiments show that our HashTables and
 * HashTable's safe iterators significantly outperform the standard library
 * unordered_maps). Of course, if there is no possibility for an iterator to
 * point to a deleted element, the user can use the "unsafe" iterators
 * HashTableIterator and HashTableConstIterator (a.k.a. HashTable<>::iterator
 * and HashTable<>::const_iterator). These iterators are slightly faster than
 * their safe counterparts. However, as in the standard library, accessing
 * through them a deleted element usually results in a mess (most probably a
 * segfault).
 *
 * @warning HashTables @b guarantee that any element stored within them will
 * have the @b same @b location in memory until it is removed from the
 * hashtable (and this holds whatever operation is performed on the hashtable
 * like new insertions, deletions, resizing, etc.).
 *
 * @par Usage example:
 * @code
 * // creation of an empty hash table
 * HashTable<int,string> table1;
 *
 * // insert two elements into the hash table
 * table1.insert (10,"xxx");
 * table1.insert (20,"yyy");
 * table1.emplace (30,"zzz");
 *
 * // creation of a nonempty hashtable using initializer lists
 * HashTable<int,bool> table { std::make_pair (3,true), std::make_pair(2,false)
 * };
 *
 * // display the content of the hash table
 * cerr << table1;
 *
 * // get the number of elements stored into the hash table
 * cerr << "number of elements in table1 = " << table1.size () << endl;
 *
 * // create two copies of the hash table
 * HashTable<int,string> table2, table3 = table1;
 * table2 = table3;
 *
 * // get the element whose key is 10
 * cerr << table1[10] << " = xxx" << endl;
 *
 * // check whether there exists an element with key 20
 * if (table1.exists (20)) cerr << "element found" << endl;
 *
 * // transform the hashtable of string into a hashtable of int assuming f is
 * // defined as: int f (const string& str) { return str.size (); }
 * HashTable<int,int> table = table1.map (f);
 *
 * // remove two elements from table1 and table2
 * table1.erase (10);         // key = 10
 * table1.eraseByVal ("yyy"); // val = "yyy"
 * table2.clear ();
 *
 * // check whether the hash table is empty
 * if (!table1.empty ()) cerr << "table not empty" << endl;
 *
 * // check wether hashtables contain the same elements
 * if ((table1 == table2) && (table1 != table3))
 *   cerr << "check for equality/inequality" << endl;
 *
 * // parse the content of a hashtable using an unsafe iterator
 * for (HashTable<int,string>::const_iterator iter = table1.cbegin();
 *       iter != table1.cend(); ++iter)
 *   cerr << *iter;
 * HashTable<int,string>::iterator iter = table1.begin();
 * iter += 2;
 * cerr << iter.key () << " " << iter.val ();
 *
 * // use an iterator to point the element we wish to erase
 * HashTable<int,string>::iterator_safe iterS = table1.beginSafe ();
 * table1.erase ( table1.beginSafe () + 4 );
 * table1.erase ( iterS ); // this is safe because the iterator is safe
 *
 * // check for iterator's safety
 * for (HashTable<int,string>::iterator_safe iter = table1.beginSafe ();
 *       iter != table1.endSafe (); ++iter )
 *   table1.eraseByVal ( *iter );
 * @endcode
 *
 * @warning @b agrum/base/core/set_tpl.h To speed-up accessors in sets, we rely on the
 * fact (which holds currently) that hashTable's iterators end are never
 * modified by insertions or deletions of elements in hash tables. If this
 * property were to be changed, set_tpl.h should be updated accordingly.
 *
 * @warning @b agrum/base/core/bijection_tpl.h Same as set_tpl.h but, in addition,
 * bijections assume that once a pair (key,val) has been created in the
 * hashtable, its location in memory will never change, even if the hashtable
 * is resized.
 *
 * @warning @b agrum/base/core/sequence_tpl.h Same as bijection_tpl.h.
 *
 * @warning @b agrum/base/core/priorityQueue_tpl.h Same as bijection_tpl.h.
 *
 * @warning @b agrum/base/core/heap_tpl.h Same as bijection_tpl.h.
 *
 * @}
 *
 * \defgroup hashfunctions_group Hash functions
 * @{
 * @brief This module lists all hash functions provided by aGrUM.
 *
 * Whenever you create a new hash function you must inherit from this class.
 * Otherwise, your hash function will not compile because gum::HashTable will
 * refer directly to this class.
 *
 * The way gum::HashTable work, you do not need to define constructors,
 * destructors and assignment operators: the defaults created by C++ will
 * work correctly. However, if your hash function contains new attributes,
 * you must override the resize function to properly set these attributes.
 * You may even have to redefine the default constructor and/or the
 * assignment operator, but this should not occur very often.
 *
 * In fact, usually, when you create a new hash function, you will only need
 * to write something like:
 *
 * @code
 * template <> class HashFunc<MyObject> : public HashFuncBase<MyObject> {
 * public:
 *   Size operator() (const MyObject& key) const  {
 *      // here write the code using
 *      // HashFuncBase<MyObject>::_hash_size and/or
 *      // HashFuncBase<MyObject>::_hash_log2_size and/or
 *      // HashFuncBase<MyObject>::_hash_mask
 *   }
 * };
 * @endcode
 *
 * For instance, here is how HashFunc<string> is implemented:
 *
 * @code
 * template <> class HashFunc<std::string>: public HashFuncBase<std::string> {
 * public:
 *   Size operator() (const std::string& key) const  {
 *     Size h = 0;
 *     for (size_t i = 0, j = key.size(); i < j; ++i) {
 *       h = 19 * h + key[i];
 *     }
 *     return ((h * GUM_HASHTABLE_INT_GOLD) & _hash_mask);
 *   }
 * };
 * @endcode
 *
 * The gum::HashFunc::_hash_size attribute corresponds to the number of slots
 * in the gum::HashTable. Your function should always return a number in
 * [0,_hash_size). As the number of slots in a gum::HashTable is always a
 * power of 2, it may be convenient to know the number of bits used by the
 * hashed keys, this is precisely the information contained in
 * gum::HashFunc::_hash_log2_size. Finally, gum::HashFunc::_hash_mask is a
 * mask that can be used to ensure that the hashed key actually belongs to
 * [0,_hash_size). This is used in particular in the hash function for
 * hashing strings.
 *
 * @}
 *
 * \defgroup bijection_group Bijections
 * @{
 * @brief Set of pairs of elements with fast search for both elements.
 *
 * The gum::Bijection class is designed for modeling a gum::Bijection between
 * two sets, the idea is following :
 *  - We want to create a gum::Bjection relation between type T1 and type T2,
 *  - For x in T1, there exists only one y in T2 associated to x,
 *  - For y in T2, there exists only one x in T1 associated to y,
 *  - The user inserts all the (x, y) associations and can search efficiently
 *  the values thus associated.
 *
 * @}
 *
 * \defgroup heap_group Heaps
 * @{
 * @brief An implementation of heaps.
 *
 * This file provides class Heap that implements a classic heap. Elements are
 * sorted according to a weak order which is < by default, i.e., the top
 * element of the heap is the smallest element and the more to the bottom the
 * greater the element.
 * @par Usage example:
 * @code
 * // create a heap of integers, the top element is the smallest element
 * Heap<int> heap1;
 *
 * // create a heap of floats, the top element is the greatest
 * Heap< float,std::greater<float> > heap2;
 *
 * // insert elements into the heap
 * heap1.insert (8);
 * heap1.insert (10);
 * heap1.insert (2);
 * heap1.insert (23);
 * heap1.insert (24);
 * heap1.insert (10);
 * heap1.insert (10);
 *
 * // copy a heap into another heap
 * Heap<int> heap2 = heap1;
 *
 * // get the number of elements of the heap
 * std::cerr << heap2.size() << std::endl;
 *
 * // get the top element but do not remove it
 * std::cerr << heap2.top() << std::endl;
 *
 * // get and remove the top element of the heap
 * std::cerr << heap2.pop() << std::endl;
 *
 * // remove the top element but do not return it (faster than above)
 * heap2.eraseTop();
 *
 * // erase in heap1 value 8
 * heap1.eraseByVal (8);
 *
 * // erase element at position 3 (see function erase for the meaning of
 * // position 3)
 * heap1.erase (3);
 *
 * // get the element at position 3
 * heap1[3];
 *
 * // check whether element 24 belongs to the heap
 * heap1.contains (24);
 * @endcode
 *
 * @}
 *
 * \defgroup list_group Lists
 * @{
 *
 * This file provides class List for manipulating generic lists as well as
 * List<>::iterator, List<>::const_iterator, List<>::iterator_safe and
 * List<>::const_iterator_safe for parsing lists. The List and their (safe)
 * iterators provided here differ from those of the C++ standard library in
 * that they are "safe", i.e., deleting elements which are pointed to by
 * iterators does never produce any segmentation fault nor unexpected results
 * when the iterators are incremented or decremented. Tests performed on a
 * Fedora Core 3 with programs compiled with g++ 3.4 show that List and their
 * iterators are as fast as their counterparts in the standard library. If
 * computation times are an issue, the "_unsafe" iterators provide fast access
 * (but at the expense of safety: dereferencing an unsafe iterator pointing to
 * an erased element will most certainly induce a segfault (like the STL).
 *
 * @warning Developers should keep in mind that whenever a value is inserted
 * into a List, unless it is an R-value, it is actually a copy of this value
 * that is inserted into the List (much like what happens in C++ standard
 * library).  However, when inserting rvalues, move insertions are provided.
 *
 * @par Usage example:
 * @code
 * // creation of an empty list
 * List<int> list1;
 * List<int> list2 { 3, 4, 5 }; // initializer list
 *
 * // adding elements to the list
 * list1.pushFront (23);
 * list1.pushBack (10);
 * list1 += 25;
 * list1.insert (12);
 * list.emplaceBack (22);
 * list.emplaceFront (10);
 *
 * // getting the second element of the list
 * cerr << "10 = " << list1[2] << endl;
 *
 * // getting the first and last elements
 * cerr << "first = " << list1.front() << " last = " << list1.back() << endl;
 *
 * // get the number of elements in the list
 * cerr << "number of elements = " << list1.size () << endl;
 *
 * // display the content of the list
 * cerr << list1 << endl;
 *
 * // copy the list
 * List<int> list2 = list1, list3;
 * list3 = list1;
 *
 * // delete the second element from the list
 * list1.erase (1);
 *
 * // delete the first and last elements
 * list1.popFront ();
 * list1.popBack ();
 *
 * // delete element whose value is 25
 * list1.eraseByVal (25);
 *
 * // check whether the list is empty
 * if (list1.empty()) cerr << "empty list" << endl;
 *
 * // remove all elements from the list
 * list1.clear ();
 *
 * // parse all the elements of a list with unsafe iterators
 * for (List<int>::iterator iter = list2.begin();
 *      iter != list2.end(); ++iter)
 *   cerr << *iter << endl;
 * for (List<int>::iterator iter = list2.rbegin();
 *      iter != list2.rend(); --iter)
 *   cerr << *iter << endl;
 * for (List<int>::const_iterator iter = list2.cbegin();
 *      iter != list2.cend(); ++iter)
 *   cerr << *iter << endl;
 * for (List<int>::const_iterator iter = list2.crbegin();
 *      iter != list2.crend(); --iter)
 *   cerr << *iter << endl;
 *
 * // parse all the elements of a list with safe iterators
 * for (List<int>::iterator_safe iter = list2.beginSafe();
 *      iter != list2.endSafe(); ++iter)
 *   cerr << *iter << endl;
 * for (List<int>::iterator_safe iter = list2.rbeginSafe();
 *      iter != list2.rendSafe(); --iter)
 *   cerr << *iter << endl;
 * for (List<int>::const_iterator_safe iter = list2.cbeginSafe();
 *      iter != list2.cendSafe(); ++iter)
 *   cerr << *iter << endl;
 * for (List<int>::const_iterator_safe iter = list2.crbeginSafe();
 *      iter != list2.crendSafe(); --iter)
 *   cerr << *iter << endl;
 *
 * // use an iterator to point the element we wish to erase
 * List<int>::iterator_safe iter = list2.beginSafe ();
 * List2.erase ( iter );
 * List<int>::iterator iter2 = list2.begin() + 4; // 5th element of the list
 * iter2 = iter + 4;
 *
 * // map a list into another list (assuming function f is defined as
 * // float f (int x) { return (2.5 * x); } )
 * List<float> flist = list2.map (f);
 * @endcode
 *
 * @}
 *
 * \defgroup priorityqueue_group Priority queue
 * @{
 * This file provides class MultiPriorityQueue that is essentially a heap in
 * which elements are sorted according to a dynamically modifiable priority. As
 * in heaps, elements are sorted according to a weak order which is < by
 * default, i.e., the top element of the queue is the smallest element and the
 * more to the bottom the greater the element.
 *
 * @par Usage example:
 * @code
 * // create a priority queue of strings, the priorities of which are integers
 * // the element at the top of the queue has the smallest priority
 * MultiPriorityQueue<std::string> queue1;
 *
 * // insert elements into the queue
 * queue1.insert (8,  "AAA");
 * queue1.insert (10, "BBB");
 * queue1.insert (2,  "CCC");
 * queue1.insert (23, "DDD");
 * queue1.insert (24, "EEE");
 * queue1.insert (10, "AAA");
 *
 * // copy the queue
 * MultiPriorityQueue<std::string> queue2 = queue1;
 *
 * // initializer list constructor
 * MultiPriorityQueue<std::string,int>
 * queue3 { std::pair<std::string,int> ( "aa", 3 ),
 *          std::pair<std::string,int> ( "bb", 2 ) };
 *
 * // create a priority queue of strings, the priorities of which are pairs of
 * // int
 * MultiPriorityQueue< std::string, std::pair<int,int> > queue3;
 *
 * // get the top element, then remove it
 * std::cerr << queue2.top() << std::endl;
 * queue2.eraseTop();
 *
 * // get the top element, then remove it
 * std::cerr << queue2.pop() << std::endl;
 *
 * // output the content of the queue
 * std::cerr << queue1 << std::endl;
 *
 * // change the priority of the element at position 3
 * Size new_pos=queue1.setPriorityByPos (3,100);
 *
 * // change the priority of all instances of element "AAA"
 * queue1.setPriority ("AAA",100);
 * @endcode
 *
 * This file provides class PriorityQueue that is essentially a heap in which
 * elements are sorted according to a dynamically modifiable priority. As in
 * heaps, elements are sorted according to a weak order which is < by default,
 * i.e., the top element of the queue is the smallest element and the more to
 * the bottom the greater the element. In addition, PriorityQueue has a special
 * feature that enables it to prevent multiple identical elements to be stored
 * into it.
 *
 * @par Usage example:
 * @code
 * // create a priority queue of strings, the priorities of which are integers
 * // the element at the top of the queue has the smallest priority
 * PriorityQueue<std::string> queue1;
 *
 * // insert elements into the queue
 * queue1.insert (8,  "AAA");
 * queue1.insert (10, "BBB");
 * queue1.insert (2,  "CCC");
 * queue1.insert (23, "DDD");
 * queue1.insert (24, "EEE");
 *
 * // copy the queue
 * PriorityQueue<std::string> queue2 = queue1;
 *
 * // initializer list constructor
 * PriorityQueue<std::string,int> queue3 { std::pair<std::string,int> ("aa", 3),
 *                                         std::pair<std::string,int> ("bb", 2 )
 * };
 *
 * // create a priority queue of strings, the priorities of which are pairs of
 * // int
 * PriorityQueue< std::string, std::pair<int,int> > queue3;
 *
 * // get the top element, then remove it
 * std::cerr << queue2.top() << std::endl;
 * queue2.eraseTop();
 *
 * // get the top element, then remove it
 * std::cerr << queue2.pop() << std::endl;
 *
 * // output the content of the queue
 * std::cerr << queue1 << std::endl;
 *
 * // change the priority of the element at position 3
 * Size new_pos=queue1.setPriorityByPos (3,100);
 *
 * // change the priority of all instances of element "AAA"
 * queue1.setPriority ("AAA",100);
 * @endcode
 *
 * @}
 *
 *
 * \defgroup sequence_group Sequences
 * @{
 *
 * A Sequence<Key> is quite similar to a vector<Key> in that it stores an
 * ordered set of elements. The main difference between these two data
 * structures lies in the fact that, given a key, it is possible to retrieve
 * from a Sequence<Key> the index in the vector where the key lies in O(1). As
 * a result, it is not possible to insert a given element twice in the
 * sequence, that is, all the Keys must be different.
 *
 * @}
 *
 * \defgroup set_group Sets
 * @{
 *
 * \brief A Set is a structure that contains arbitrary elements.
 *
 * Note that, as in mathematics, an element cannot appear twice in a given set.
 * Sets have unsafe and safe iterators. The safe iterators (SetIteratorSafe<>
 * a.k.a.  Set<>::iterator_safe are slightly slower than the unsafe ones
 * (SetIterator<> a.k.a. Set<>::iterator) but they guarantee that even if they
 * point to a deleted element, using their operators ++ or * cannot produce a
 * segfault. In such cases, they simply raise an exception. On the contrary,
 * unsafe iterators should @b never be used on elements that can be deleted
 * because, as in the STL, they will most probably produce a segfault.
 *
 * @par Usage example:
 * @code
 * // creation of a set with 10 elements
 * Set<int> set;
 * for (int i = 0; i< 10; ++i)
 *   set<<i;
 * Set<int> set2 { 1, 2, 3 };
 *
 * // parse the set
 * for (auto iter = set.begin (); iter != set.end (); ++iter) {
 *   // display the values
 *   cerr <<  *iter << endl;
 * }
 *
 * // use an iterator to point the element we wish to erase
 * Set<int>::iterator iter = set.begin ();
 * set.erase ( iter );
 *
 * // check whether two iterators point toward the same element
 * Set<int>::iterator iter1 = set.begin();
 * Set<int>::iterator iter2 = set.end();
 * if (iter1 != iter2)
 *   cerr << "iter1 and iter2 point toward different elements";
 *
 * @endcode
 *
 * @}
 *
 * \defgroup splaytree_group Splay Trees
 * @{
 *
 * \brief A splay tree is a self-balancing binary search tree.
 *
 * @}
 *
 * @}
 */
