Loading [MathJax]/extensions/tex2jax.js

Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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