Arcane  v3.14.10.0
Documentation utilisateur
Chargement...
Recherche...
Aucune correspondance
HashTable.h
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2023 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7/*---------------------------------------------------------------------------*/
8/* HashTable.h (C) 2000-2023 */
9/* */
10/* Table de hachage. */
11/*---------------------------------------------------------------------------*/
12#ifndef ARCANE_UTILS_HASHTABLE_H
13#define ARCANE_UTILS_HASHTABLE_H
14/*---------------------------------------------------------------------------*/
15/*---------------------------------------------------------------------------*/
16
17#include "arcane/utils/MultiBuffer.h"
18#include "arcane/utils/Array.h"
19#include "arcane/utils/HashFunction.h"
20
21/*---------------------------------------------------------------------------*/
22/*---------------------------------------------------------------------------*/
23
24namespace Arcane
25{
26
27/*---------------------------------------------------------------------------*/
28/*---------------------------------------------------------------------------*/
29/*!
30 * \internal
31 * \brief Classe de base d'une table de hachage simple pour les entités
32
33 \todo Ajouter des itérateurs pour cette collection et les classes
34 dérivées
35 */
36class ARCANE_UTILS_EXPORT HashTableBase
37{
38 public:
39
40 /*! \brief Crée une table de taille \a table_size
41 *
42 Si \a use_prime est vrai, utilise la fonction nearestPrimeNumber()
43 pour avoir une taille de taille qui est un nombre premier.
44 */
45 HashTableBase(Integer table_size, bool use_prime)
46 : m_count(0)
47 , m_nb_bucket(use_prime ? nearestPrimeNumber(table_size) : table_size)
48 {
49 }
50 virtual ~HashTableBase() {}
51
52 public:
53
54 /*! \brief Retourne le nombre premier le plus proche de \a n par excès.
55 * Le nombre premier le plus proche et supérieur à \a n est renvoyé en utilisant une
56 * table de nombre premier déterminée à l'avance.
57 */
58 Integer nearestPrimeNumber(Integer n);
59
60 public:
61
62 //! Nombre d'éléments dans la table
63 Integer count() const
64 {
65 return m_count;
66 }
67
68 protected:
69
70 void _throwNotFound ARCANE_NORETURN() const;
71
72 protected:
73
74 Integer m_count; //!< Nombre d'éléments
75 Integer m_nb_bucket; //!< Nombre de buckets
76};
77
78/*---------------------------------------------------------------------------*/
79/*---------------------------------------------------------------------------*/
80/*!
81 * \internal
82 * \brief Classe de base d'une table de hachage pour tableaux associatifs
83
84 Cette table permet de stocker une valeur en fonction d'une clé. Le
85 type de la valeur est gérée par la classe dérivée HashTableMapT.
86
87 La table de hachage est gérée sous forme d'un tableau dont le nombre
88 d'éléments est donné par la taille de la table (m_nb_bucket).
89 Les éléments sont ensuite rangés dans une liste chaînée.
90
91 Cette table permet uniquement d'ajouter des valeurs.
92
93 Pour des raisons de performance, il est préférable que le taille
94 de la table (buckets) soit un nombre premier.
95 */
96template <typename KeyType, typename TraitsType>
98: public HashTableBase
99{
100 public:
101
102 typedef typename TraitsType::KeyTypeConstRef KeyTypeConstRef;
103 typedef typename TraitsType::KeyTypeValue KeyTypeValue;
104
105 public:
106
107 struct HashData
108 {
109 public:
110
111 friend class HashTableBaseT<KeyType, TraitsType>;
112
113 public:
114
115 HashData()
116 : m_key(KeyType())
117 , m_next(0)
118 {}
119
120 public:
121
122 /*! \brief Change la valeur de la clé.
123 *
124 * Après avoir changé la valeur d'une ou plusieurs clés, il faut faire un rehash().
125 */
126 void changeKey(const KeyType& new_key)
127 {
128 m_key = new_key;
129 }
130
131 protected:
132
133 KeyTypeValue m_key; //!< Clé de recherche
134 HashData* m_next; //! Elément suivant dans la table de hachage
135 };
136
137 public:
138
139 /*! \brief Crée une table de taille \a table_size
140 *
141 Si \a use_prime est vrai, utilise la fonction nearestPrimeNumber()
142 pour avoir une taille de taille qui est un nombre premier.
143 */
144 HashTableBaseT(Integer table_size, bool use_prime)
145 : HashTableBase(table_size, use_prime)
146 , m_buckets(m_nb_bucket)
147 {
148 m_buckets.fill(0);
149 }
150
151 public:
152
153 //! \a true si une valeur avec la clé \a id est présente
154 bool hasKey(KeyTypeConstRef id) const
155 {
156 KeyType hf = _hash(id);
157 for (HashData* i = m_buckets[hf]; i; i = i->m_next) {
158 if (i->m_key == id)
159 return true;
160 }
161 return false;
162 }
163
164 //! Supprime tous les éléments de la table
165 void clear()
166 {
167 m_buckets.fill(0);
168 m_count = 0;
169 }
170
171 //! Redimensionne la table de hachage
172 void resize(Integer new_table_size, bool use_prime = false)
173 {
174 m_nb_bucket = new_table_size;
175 if (new_table_size == 0) {
176 clear();
177 return;
178 }
179 if (use_prime)
180 new_table_size = nearestPrimeNumber(new_table_size);
181 //todo: supprimer l'allocation de ce tableau
182 UniqueArray<HashData*> old_buckets(m_buckets.clone());
183 m_buckets.resize(new_table_size);
184 m_buckets.fill(0);
185 for (Integer z = 0, zs = old_buckets.size(); z < zs; ++z) {
186 for (HashData* i = old_buckets[z]; i; i = i->m_next) {
187 _baseAdd(_hash(i->m_key), i->m_key, i);
188 }
189 }
190 }
191
192 //! Repositionne les données après changement de valeur des clés
193 void rehash()
194 {
195 //todo: supprimer l'allocation de ce tableau
196 UniqueArray<HashData*> old_buckets(m_buckets.clone());
197 m_buckets.fill(0);
198
199 for (Integer z = 0, zs = old_buckets.size(); z < zs; ++z) {
200 for (HashData* i = old_buckets[z]; i;) {
201 HashData* current = i;
202 i = i->m_next; // Il faut le faire ici, car i->m_next change avec _baseAdd
203 _baseAdd(_hash(current->m_key), current->m_key, current);
204 }
205 }
206 }
207
208 protected:
209
210 inline Integer _hash(KeyTypeConstRef id) const
211 {
212 return TraitsType::hashFunction(id) % m_nb_bucket;
213 }
214 inline HashData* _baseLookupBucket(Integer bucket, KeyTypeConstRef id) const
215 {
216 for (HashData* i = m_buckets[bucket]; i; i = i->m_next) {
217 if (i->m_key == id)
218 return i;
219 }
220 return 0;
221 }
222 inline HashData* _baseRemoveBucket(Integer bucket, KeyTypeConstRef id)
223 {
224 HashData* i = m_buckets[bucket];
225 if (i) {
226 if (i->m_key == id) {
227 m_buckets[bucket] = i->m_next;
228 --m_count;
229 return i;
230 }
231 for (; i->m_next; i = i->m_next) {
232 if (i->m_next->m_key == id) {
233 HashData* r = i->m_next;
234 i->m_next = i->m_next->m_next;
235 --m_count;
236 return r;
237 }
238 }
239 }
240 _throwNotFound();
241 }
242 inline HashData* _baseLookup(KeyTypeConstRef id) const
243 {
244 return _baseLookupBucket(_hash(id), id);
245 }
246 inline HashData* _baseRemove(KeyTypeConstRef id)
247 {
248 return _baseRemoveBucket(_hash(id), id);
249 }
250 inline void _baseAdd(Integer bucket, KeyTypeConstRef id, HashData* hd)
251 {
252 HashData* buck = m_buckets[bucket];
253 hd->m_key = id;
254 hd->m_next = buck;
255 m_buckets[bucket] = hd;
256 ++m_count;
257 }
258
259 protected:
260
261 UniqueArray<HashData*> m_buckets; //! Tableau des buckets
262};
263
264/*---------------------------------------------------------------------------*/
265/*---------------------------------------------------------------------------*/
266
267} // namespace Arcane
268
269/*---------------------------------------------------------------------------*/
270/*---------------------------------------------------------------------------*/
271
272#endif
void rehash()
Repositionne les données après changement de valeur des clés.
Definition HashTable.h:193
HashTableBaseT(Integer table_size, bool use_prime)
Crée une table de taille table_size.
Definition HashTable.h:144
void resize(Integer new_table_size, bool use_prime=false)
Redimensionne la table de hachage.
Definition HashTable.h:172
bool hasKey(KeyTypeConstRef id) const
true si une valeur avec la clé id est présente
Definition HashTable.h:154
void clear()
Supprime tous les éléments de la table.
Definition HashTable.h:165
HashTableBase(Integer table_size, bool use_prime)
Crée une table de taille table_size.
Definition HashTable.h:45
Integer m_nb_bucket
Nombre de buckets.
Definition HashTable.h:75
Integer nearestPrimeNumber(Integer n)
Retourne le nombre premier le plus proche de n par excès. Le nombre premier le plus proche et supérie...
Definition HashTable.cc:57
Integer m_count
Nombre d'éléments.
Definition HashTable.h:74
Integer count() const
Nombre d'éléments dans la table.
Definition HashTable.h:63
Integer size() const
Nombre d'éléments du vecteur.
Vecteur 1D de données avec sémantique par valeur (style STL).
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
void changeKey(const KeyType &new_key)
Change la valeur de la clé.
Definition HashTable.h:126
KeyTypeValue m_key
Clé de recherche.
Definition HashTable.h:133