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