Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

hash.inc
Go to the documentation of this file.
1 
29 #pragma once
30 
31 namespace abacus {
32 
33 
34 template <class KeyType, class ItemType>
36  const KeyType &key,
37  const ItemType &item) :
38 key_(key),
39  item_(item),
40  next_(nullptr)
41 { }
42 
43 
44 template <class KeyType, class ItemType>
45 std::ostream &operator<<(std::ostream &out, const AbaHashItem<KeyType, ItemType> &rhs)
46 {
47  return out << '(' << rhs.key_ << ',' << rhs.item_ << ')';
48 }
49 
50 
51 template <class KeyType, class ItemType>
52 inline AbaHashItem<KeyType, ItemType> * AbaHashItem<KeyType,
53  ItemType>::next()
54 {
55  return next_;
56 }
57 
58 
59 template <class KeyType, class ItemType>
60 AbaHash<KeyType, ItemType>::AbaHash(int size)
61  : size_(size), nCollisions_(0), iter_(nullptr)
62 {
63  table_ = new AbaHashItem<KeyType, ItemType>* [size];
64 
65  for (int i = 0; i < size; i++)
66  table_[i] = nullptr;
67 }
68 
69 
70 template <class KeyType, class ItemType>
71 AbaHash<KeyType, ItemType>::~AbaHash()
72 {
73  AbaHashItem<KeyType, ItemType> *h1;
74  AbaHashItem<KeyType, ItemType> *h2;
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 
89 template <class KeyType, class ItemType>
90 std::ostream &operator<<(std::ostream &out, const AbaHash<KeyType, ItemType> &hash)
91 {
92  AbaHashItem<KeyType, ItemType> *h;
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 
110 template <class KeyType, class ItemType>
111 void AbaHash<KeyType, ItemType>::insert(
112  const KeyType &key,
113  const ItemType &item)
114 {
115  AbaHashItem<KeyType, ItemType> *h = new AbaHashItem<KeyType, ItemType>(key, item);
116  int slotNum = hf(key);
117 
118  if (table_[slotNum]) ++nCollisions_;
119  h->next_ = table_[slotNum];
120  table_[slotNum] = h;
121 }
122 
123 
124 template <class KeyType, class ItemType>
125 void AbaHash<KeyType, ItemType>::overWrite(
126  const KeyType &key,
127  const ItemType &item)
128 {
130  int slotNum = hf(key);
131  if (table_[slotNum]) ++nCollisions_;
132 
133  AbaHashItem<KeyType, ItemType> *h = table_[slotNum];
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 
153 template <class KeyType, class ItemType>
154 const ItemType * AbaHash<KeyType, ItemType>::find(const KeyType &key) const
155 {
156  const AbaHashItem<KeyType, ItemType> *slot;
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 
167 template <class KeyType, class ItemType>
168 ItemType * AbaHash<KeyType, ItemType>::find(const KeyType &key)
169 {
170  AbaHashItem<KeyType, ItemType> *slot;
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 
181 template <class KeyType, class ItemType>
182 bool AbaHash<KeyType, ItemType>::find (const KeyType &key, const ItemType &item) const
183 {
184  const AbaHashItem<KeyType, ItemType> *slot;
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 
197 template <class KeyType, class ItemType>
198 ItemType *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 
208 template <class KeyType, class ItemType>
209 const 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 
219 template <class KeyType, class ItemType>
220 ItemType *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 
232 template <class KeyType, class ItemType>
233 const 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 
245 template <class KeyType, class ItemType>
246 int AbaHash<KeyType, ItemType>::remove(const KeyType &key)
247 {
248  // remove(): find the slot and return if it is empty
249  AbaHashItem<KeyType, ItemType> *h1;
250  AbaHashItem<KeyType, ItemType> *h2;
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 
277 template <class KeyType, class ItemType>
278 int AbaHash<KeyType, ItemType>::remove(const KeyType &key, const ItemType &item)
279 {
280  // remove(): find the slot and return if it is empty
281  AbaHashItem<KeyType, ItemType> *h1;
282  AbaHashItem<KeyType, ItemType> *h2;
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 
309 template <class KeyType, class ItemType>
310 inline int AbaHash<KeyType, ItemType>::size() const
311 {
312  return size_;
313 }
314 
315 
316 template <class KeyType, class ItemType>
317 inline int AbaHash<KeyType, ItemType>::nCollisions() const
318 {
319  return nCollisions_;
320 }
321 
322 
323 template <class KeyType, class ItemType>
324 inline 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 
334 template <class KeyType, class ItemType>
335 inline 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 
343 template <class KeyType, class ItemType>
344 int 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 
361 template <class KeyType, class ItemType>
362 void 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  */
374  AbaHashItem<KeyType, ItemType> **newTable;
375 
376  newTable = new AbaHashItem<KeyType, ItemType>* [newSize];
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
395  AbaHashItem<KeyType, ItemType> *current = table_[i];
396  AbaHashItem<KeyType, ItemType> *next;
397 
398  while (current) {
399  int slotNum = hf(current->key_);
400  next = current->next_;
401 
402  current->next_ = newTable[slotNum];
403  newTable[slotNum] = current;
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 }
abacus
Definition: abacusroot.h:48
ogdf::tlp::Attribute::size
@ size
ogdf::AlgorithmFailureCode::Hash
@ Hash
abacus::AbaHashItem::AbaHashItem
AbaHashItem(const KeyType &key, const ItemType &item)
The constructor.
ogdf::operator<<
std::ostream & operator<<(std::ostream &os, const ogdf::Array< E, INDEX > &a)
Prints array a to output stream os.
Definition: Array.h:978
OGDF_THROW_PARAM
#define OGDF_THROW_PARAM(CLASS, PARAM)
Replacement for throw.
Definition: exceptions.h:67
Minisat::Internal::hash
static uint32_t hash(uint32_t x)
Definition: Map.h:38
Minisat::Internal::remove
static void remove(V &ts, const T &t)
Definition: Alg.h:36
Minisat::Internal::find
static bool find(V &ts, const T &t)
Definition: Alg.h:47