Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

Loading...
Searching...
No Matches
hash.inc
Go to the documentation of this file.
1
29#pragma once
30
31#pragma GCC visibility push(default)
32namespace abacus {
33
34
35template <class KeyType, class ItemType>
37 const KeyType &key,
38 const ItemType &item) :
39key_(key),
40 item_(item),
41 next_(nullptr)
42{ }
43
44
45template <class KeyType, class ItemType>
46std::ostream &operator<<(std::ostream &out, const AbaHashItem<KeyType, ItemType> &rhs)
47{
48 return out << '(' << rhs.key_ << ',' << rhs.item_ << ')';
49}
50
51
52template <class KeyType, class ItemType>
53inline AbaHashItem<KeyType, ItemType> * AbaHashItem<KeyType,
54 ItemType>::next()
55{
56 return next_;
57}
58
59
60template <class KeyType, class ItemType>
61AbaHash<KeyType, ItemType>::AbaHash(int size)
62 : size_(size), nCollisions_(0), iter_(nullptr)
63{
64 table_ = new AbaHashItem<KeyType, ItemType>* [size];
65
66 for (int i = 0; i < size; i++)
67 table_[i] = nullptr;
68}
69
70
71template <class KeyType, class ItemType>
72AbaHash<KeyType, ItemType>::~AbaHash()
73{
74 AbaHashItem<KeyType, ItemType> *h1;
75 AbaHashItem<KeyType, ItemType> *h2;
76 int i;
77
78 for (i = 0; i < size_; i++) {
79 if((h1 = table_[i]))
80 while (h1) {
81 h2 = h1->next_;
82 delete h1;
83 h1 = h2;
84 }
85 }
86 delete [] table_;
87}
88
89
90template <class KeyType, class ItemType>
91std::ostream &operator<<(std::ostream &out, const AbaHash<KeyType, ItemType> &hash)
92{
93 AbaHashItem<KeyType, ItemType> *h;
94 const int s = hash.size();
95
96 for (int i = 0; i < s; i++) {
97 h = hash.table_[i];
98 if (h) {
99 out << i << ':';
100 while(h) {
101 out << *h << ' ';
102 h = h->next();
103 }
104 out << std::endl;
105 }
106 }
107 return out;
108}
109
110
111template <class KeyType, class ItemType>
112void AbaHash<KeyType, ItemType>::insert(
113 const KeyType &key,
114 const ItemType &item)
115{
116 AbaHashItem<KeyType, ItemType> *h = new AbaHashItem<KeyType, ItemType>(key, item);
117 int slotNum = hf(key);
118
119 if (table_[slotNum]) ++nCollisions_;
120 h->next_ = table_[slotNum];
121 table_[slotNum] = h;
122}
123
124
125template <class KeyType, class ItemType>
126void AbaHash<KeyType, ItemType>::overWrite(
127 const KeyType &key,
128 const ItemType &item)
129{
131 int slotNum = hf(key);
132 if (table_[slotNum]) ++nCollisions_;
133
134 AbaHashItem<KeyType, ItemType> *h = table_[slotNum];
135
137
139 while (h) {
140 if (h->key_ == key) {
141 h->item_ = item;
142 return;
143 }
144 h = h->next_;
145 }
146
148 h = new AbaHashItem<KeyType, ItemType>(key, item);
149 h->next_ = table_[slotNum];
150 table_[slotNum] = h;
151}
152
153
154template <class KeyType, class ItemType>
155const ItemType * AbaHash<KeyType, ItemType>::find(const KeyType &key) const
156{
157 const AbaHashItem<KeyType, ItemType> *slot;
158
159 slot = table_[hf(key)];
160
161 while (slot) {
162 if (key == slot->key_) return &(slot->item_);
163 slot = slot->next_;
164 }
165 return nullptr;
166}
167
168template <class KeyType, class ItemType>
169ItemType * AbaHash<KeyType, ItemType>::find(const KeyType &key)
170{
171 AbaHashItem<KeyType, ItemType> *slot;
172
173 slot = table_[hf(key)];
174
175 while (slot) {
176 if (key == slot->key_) return &(slot->item_);
177 slot = slot->next_;
178 }
179 return 0;
180}
181
182template <class KeyType, class ItemType>
183bool AbaHash<KeyType, ItemType>::find (const KeyType &key, const ItemType &item) const
184{
185 const AbaHashItem<KeyType, ItemType> *slot;
186
187 slot = table_[hf(key)];
188
189 while (slot) {
190 if (key == slot->key_ && slot->item_ == item)
191 return true;
192 slot = slot->next_;
193 }
194 return false;
195}
196
197
198template <class KeyType, class ItemType>
199ItemType *AbaHash<KeyType, ItemType>::initializeIteration(const KeyType &key)
200{
201 iter_ = table_[hf(key)];
202 while (iter_) {
203 if (key == iter_->key_) return &(iter_->item_);
204 iter_ = iter_->next_;
205 }
206 return nullptr;
207}
208
209template <class KeyType, class ItemType>
210const ItemType *AbaHash<KeyType, ItemType>::initializeIteration(const KeyType &key) const
211{
212 iter_ = table_[hf(key)];
213 while (iter_) {
214 if (key == iter_->key_) return &(iter_->item_);
215 iter_ = iter_->next_;
216 }
217 return nullptr;
218}
219
220template <class KeyType, class ItemType>
221ItemType *AbaHash<KeyType, ItemType>::next(const KeyType &key)
222{
223 if (iter_ == nullptr) return nullptr;
224 iter_ = iter_->next_;
225
226 while (iter_) {
227 if (key == iter_->key_) return &(iter_->item_);
228 iter_ = iter_->next();
229 }
230 return nullptr;
231}
232
233template <class KeyType, class ItemType>
234const ItemType *AbaHash<KeyType, ItemType>::next(const KeyType &key) const
235{
236 if (iter_ == nullptr) return nullptr;
237 iter_ = iter_->next_;
238
239 while (iter_) {
240 if (key == iter_->key_) return &(iter_->item_);
241 iter_ = iter_->next();
242 }
243 return nullptr;
244}
245
246template <class KeyType, class ItemType>
247int AbaHash<KeyType, ItemType>::remove(const KeyType &key)
248{
249 // remove(): find the slot and return if it is empty
250 AbaHashItem<KeyType, ItemType> *h1;
251 AbaHashItem<KeyType, ItemType> *h2;
252 int slotNum = hf(key);
253
254 h1 = table_[slotNum];
255 if (h1 == 0)
256 return 1;
257
258 // check if the first item is being removed
259 if (h1->key_ == key) {
260 table_[slotNum] = h1->next_;
261 delete h1;
262 return 0;
263 }
264
265 // otherwise, go through the linked list
266 while ((h2 = h1->next_)) {
267 if (h2->key_ == key) {
268 h1->next_ = h2->next_;
269 delete h2;
270 return 0;
271 }
272 h1 = h2;
273 }
274 return 1;
275}
276
277
278template <class KeyType, class ItemType>
279int AbaHash<KeyType, ItemType>::remove(const KeyType &key, const ItemType &item)
280{
281 // remove(): find the slot and return if it is empty
282 AbaHashItem<KeyType, ItemType> *h1;
283 AbaHashItem<KeyType, ItemType> *h2;
284 int slotNum = hf(key);
285
286 h1 = table_[slotNum];
287 if (h1 == nullptr)
288 return 1;
289
290 // check \a key and \a item of the head of the list
291 if (h1->key_ == key && h1->item_ == item) {
292 table_[slotNum] = h1->next_;
293 delete h1;
294 return 0;
295 }
296
297 // check \a key and \a item of the other elements of the list
298 while ((h2 = h1->next_)) {
299 if (h2->key_ == key && h2->item_ == item) {
300 h1->next_ = h2->next_;
301 delete h2;
302 return 0;
303 }
304 h1 = h2;
305 }
306 return 1;
307}
308
309
310template <class KeyType, class ItemType>
311inline int AbaHash<KeyType, ItemType>::size() const
312{
313 return size_;
314}
315
316
317template <class KeyType, class ItemType>
318inline int AbaHash<KeyType, ItemType>::nCollisions() const
319{
320 return nCollisions_;
321}
322
323
324template <class KeyType, class ItemType>
325inline int AbaHash<KeyType, ItemType>::hf(int key) const
326{
327 if (key < 0) key = -key;
328
329 double x = key*0.6180339887;
330
331 return (int) (size()*(x-floor(x)));
332}
333
334
335template <class KeyType, class ItemType>
336inline int AbaHash<KeyType, ItemType>::hf(unsigned key) const
337{
338 double x = key*0.6180339887;
339
340 return (int) (size()*fmod(x, 1.0));
341}
342
343
344template <class KeyType, class ItemType>
345int AbaHash<KeyType, ItemType>::hf(const string &str) const
346{
347 const int prime = 516595003;
348 const int mult = 314159;
349
350 string::size_type s = str.size();
351 int h = 0;
352 for (string::size_type i = 0; i < s; i++) {
353 h += (h ^ (h >> 1)) + mult * (unsigned char) str[i];
354 while (h >= prime)
355 h -= prime;
356 }
357
358 return h % size();
359}
360
361
362template <class KeyType, class ItemType>
363void AbaHash<KeyType, ItemType>::resize(int newSize)
364{
365 // check the value of \a newSize
366 if (newSize <= 0) {
367 Logger::ifout() << "AbaHash::resize(): new size of hash table must be positive.\n";
368 OGDF_THROW_PARAM(AlgorithmFailureException, ogdf::AlgorithmFailureCode::Hash);
369 }
370
371 // allocate a new hash table
372 /* We have to set the entries of the new hash table to 0 that we
373 * can insert the items in the linear lists of the slots in a simple way later.
374 */
375 AbaHashItem<KeyType, ItemType> **newTable;
376
377 newTable = new AbaHashItem<KeyType, ItemType>* [newSize];
378
379 for (int i = 0; i < newSize; i++)
380 newTable[i] = nullptr;
381
382 // insert all elements of the old table into the new table
383 /* We cannot make copies of slots of the old hash tables but have to reinsert
384 * all elements into the new hash table since the hash function might have
385 * changed. For efficieny we move each hash item to the new slot.
386 *
387 * We replace already here the old size with the new size of the hash table,
388 * because we need the hash function according to the new size.
389 */
390 int oldSize = size_;
391 size_ = newSize;
392
393 for (int i = 0; i < oldSize; i++) {
394 if (table_[i]) {
395 // move the items to the corresponding new slots
396 AbaHashItem<KeyType, ItemType> *current = table_[i];
397 AbaHashItem<KeyType, ItemType> *next;
398
399 while (current) {
400 int slotNum = hf(current->key_);
401 next = current->next_;
402
403 current->next_ = newTable[slotNum];
404 newTable[slotNum] = current;
405 current = next;
406 }
407
408 }
409 }
410
411 // replace the old table by the new one
412 delete [] table_;
413 table_ = newTable;
414}
415
416}
417#pragma GCC visibility pop
AbaHashItem(const KeyType &key, const ItemType &item)
The constructor.
#define OGDF_THROW_PARAM(CLASS, PARAM)
Replacement for throw.
Definition exceptions.h:58
std::ostream & operator<<(std::ostream &os, const ogdf::Array< E, INDEX > &a)
Prints array a to output stream os.
Definition Array.h:983