00001
00002
00003
00004
00005
00006
00007
00008
00046 #ifdef _MSC_VER
00047 #pragma once
00048 #endif
00049
00050 #ifndef OGDF_HASHING_H
00051 #define OGDF_HASHING_H
00052
00053 #include <ogdf/basic/basic.h>
00054 #include <math.h>
00055 #include <limits.h>
00056
00057
00058 namespace ogdf {
00059
00060 class HashingBase;
00061
00068 class HashElementBase {
00069 friend class HashingBase;
00070
00071 HashElementBase *m_next;
00072 size_t m_hashValue;
00073
00074 public:
00076 HashElementBase(size_t hashValue) : m_hashValue(hashValue) { }
00077
00079 HashElementBase *next() const { return m_next; }
00080
00082 size_t hashValue() const { return m_hashValue; }
00083
00084 OGDF_NEW_DELETE
00085 };
00086
00087
00094 class HashingBase {
00095 protected:
00096 int m_tableSize;
00097 int m_hashMask;
00098 int m_minTableSize;
00099 int m_tableSizeLow;
00100 int m_tableSizeHigh;
00101 int m_count;
00102 HashElementBase **m_table;
00103
00104 public:
00106 HashingBase(int minTableSize);
00107
00109 HashingBase(const HashingBase &H);
00110
00111
00112 virtual ~HashingBase();
00113
00115 void resize(int newTableSize);
00116
00118 void insert(HashElementBase *pElement);
00119
00121 void del(HashElementBase *pElement);
00122
00124 void clear();
00125
00127 HashingBase &operator=(const HashingBase &H);
00128
00130 int size() const { return m_count; }
00131
00133 int empty() const { return (m_count==0); }
00134
00140 HashElementBase *firstListElement(size_t hashValue) const {
00141 return *(m_table + (hashValue & m_hashMask));
00142 }
00143
00152 HashElementBase *firstElement(HashElementBase ***pList) const;
00153
00163 HashElementBase *nextElement(HashElementBase ***pList,
00164 HashElementBase *pElement) const;
00165
00166 protected:
00168 void destroyAll();
00169
00176 virtual void destroy(HashElementBase *pElement) = 0;
00177
00179 virtual HashElementBase *copy(HashElementBase *pElement) const = 0;
00180
00181 private:
00183 void init(int tableSize);
00184
00186 void copyAll(const HashingBase &H);
00187 };
00188
00189
00190 template<class K, class I, class H> class Hashing;
00191 template<class K, class I, class H> class HashArray;
00192
00193
00201 template<class K, class I>
00202 class HashElement : public HashElementBase
00203 {
00204 K m_key;
00205 I m_info;
00206
00207 public:
00209 HashElement(size_t hashValue, const K &key, const I &info) :
00210 HashElementBase(hashValue), m_key(key), m_info(info) { }
00211
00213 HashElement<K,I> *next() const {
00214 return (HashElement<K,I> *)HashElementBase::next();
00215 }
00216
00218 const K &key() const { return m_key; }
00219
00221 const I &info() const { return m_info; }
00222
00224 I &info() { return m_info; }
00225
00226 OGDF_NEW_DELETE
00227 };
00228
00229
00230 template<class K, class I, class H> class HashConstIterator;
00231
00232
00233
00234
00235
00236
00237
00238
00247 template<class K> class DefHashFunc {
00249 public: size_t hash(const K &key) const { return size_t(key); }
00250 };
00251
00253 template<> class DefHashFunc<void *> {
00254 public: size_t hash(const void * &key) const { return size_t(key && 0xffffffff); }
00255 };
00256
00258 template<> class DefHashFunc<double> {
00259 public: size_t hash(const double &key) const {
00260 int dummy;
00261 return size_t(SIZE_MAX*frexp(key,&dummy));
00262 }
00263 };
00264
00265
00279 template<class K, class I, class H = DefHashFunc<K> >
00280 class Hashing : private HashingBase
00281 {
00282 friend class HashConstIterator<K,I,H>;
00283 H m_hashFunc;
00284
00285 public:
00287 typedef HashConstIterator<K,I,H> const_iterator;
00288
00290 explicit Hashing(int minTableSize = 256, const H &hashFunc = H())
00291 : HashingBase(minTableSize), m_hashFunc(hashFunc) { }
00292
00294 Hashing(const Hashing<K,I> &h) : HashingBase(h) { }
00295
00296
00297 ~Hashing() { HashingBase::destroyAll(); }
00298
00300 int size() const { return HashingBase::size(); }
00301
00303 bool empty() const { return (HashingBase::size() == 0); }
00304
00306 bool member(const K &key) const { return (lookup(key) != 0); }
00307
00309 HashConstIterator<K,I,H> begin() const;
00310
00312 HashElement<K,I> *lookup(const K &key) const {
00313 HashElement<K,I> *pElement =
00314 (HashElement<K,I> *)firstListElement(m_hashFunc.hash(key));
00315 for (; pElement; pElement = pElement->next())
00316 if (pElement->key() == key) return pElement;
00317
00318 return 0;
00319 }
00320
00322 Hashing<K,I> &operator=(const Hashing<K,I> &hashing) {
00323 HashingBase::operator =(hashing);
00324 m_hashFunc = hashing.m_hashFunc;
00325 return *this;
00326 }
00327
00335 HashElement<K,I> *insert(const K &key, const I &info) {
00336 HashElement<K,I> *pElement = lookup(key);
00337
00338 if (pElement)
00339 pElement->info() = info;
00340 else
00341 HashingBase::insert(pElement =
00342 OGDF_NEW HashElement<K,I>(m_hashFunc.hash(key),key,info));
00343
00344 return pElement;
00345 }
00346
00354 HashElement<K,I> *insertByNeed(const K &key, const I &info) {
00355 HashElement<K,I> *pElement = lookup(key);
00356
00357 if (!pElement)
00358 HashingBase::insert(pElement = OGDF_NEW HashElement<K,I>(m_hashFunc.hash(key),key,info));
00359
00360 return pElement;
00361 }
00362
00369 HashElement<K,I> *fastInsert(const K &key, const I &info) {
00370 HashElement<K,I> *pElement = OGDF_NEW HashElement<K,I>(m_hashFunc.hash(key),key,info);
00371 HashingBase::insert(pElement);
00372 return pElement;
00373 }
00374
00376 void del(const K &key) {
00377 HashElement<K,I> *pElement = lookup(key);
00378 if (pElement) {
00379 HashingBase::del(pElement);
00380 delete pElement;
00381 }
00382 }
00383
00385 void clear() { HashingBase::clear(); }
00386
00387 protected:
00396 HashElement<K,I> *firstElement(HashElement<K,I> ***pList) const {
00397 return (HashElement<K,I> *)(HashingBase::firstElement((HashElementBase ***)pList));
00398 }
00399
00409 HashElement<K,I> *nextElement(HashElement<K,I> ***pList,
00410 HashElement<K,I> *pElement) const
00411 {
00412 return (HashElement<K,I> *)(HashingBase::nextElement(
00413 (HashElementBase ***)pList,pElement));
00414 }
00415
00416 private:
00418 virtual void destroy(HashElementBase *pElement) {
00419 delete (HashElement<K,I> *)(pElement);
00420 }
00421
00423 virtual HashElementBase *copy(HashElementBase *pElement) const {
00424 HashElement<K,I> *pX = (HashElement<K,I> *)(pElement);
00425 return OGDF_NEW HashElement<K,I>(pX->hashValue(),pX->key(),pX->info());
00426 }
00427 };
00428
00429
00453 template<class K, class I, class H = DefHashFunc<K> >
00454 class HashConstIterator {
00455 HashElement<K,I> *m_pElement;
00456 HashElement<K,I> **m_pList;
00457 const Hashing<K,I,H> *m_pHashing;
00458
00459 public:
00461 HashConstIterator() : m_pElement(0), m_pList(0), m_pHashing(0) { }
00462
00464 HashConstIterator(HashElement<K,I> *pElement, HashElement<K,I> **pList,
00465 const Hashing<K,I,H> *pHashing) : m_pElement(pElement), m_pList(pList),
00466 m_pHashing(pHashing) { }
00467
00469 HashConstIterator(const HashConstIterator<K,I,H> &it) : m_pElement(it.m_pElement),
00470 m_pList(it.m_pList), m_pHashing(it.m_pHashing) { }
00471
00473 HashConstIterator &operator=(const HashConstIterator<K,I,H> &it) {
00474 m_pElement = it.m_pElement;
00475 m_pList = it.m_pList;
00476 m_pHashing = it.m_pHashing;
00477 return *this;
00478 }
00479
00481 bool valid() const { return (m_pElement != 0); }
00482
00484 const K &key() const { return m_pElement->key(); }
00485
00487 const I &info() const { return m_pElement->info(); }
00488
00490 friend bool operator==(const HashConstIterator<K,I,H> &it1,
00491 const HashConstIterator<K,I,H> &it2) { return (it1.m_pElement == it2.m_pElement); }
00492
00494 friend bool operator!=(const HashConstIterator<K,I,H> &it1,
00495 const HashConstIterator<K,I,H> &it2) { return (it1.m_pElement != it2.m_pElement); }
00496
00498 HashConstIterator<K,I,H> &operator++() {
00499 m_pElement = m_pHashing->nextElement(&m_pList,m_pElement);
00500 return *this;
00501 }
00502 };
00503
00504
00505 template<class K, class I, class H>
00506 inline HashConstIterator<K,I,H> Hashing<K,I,H>::begin() const
00507 {
00508 HashElement<K,I> *pElement, **pList;
00509 pElement = firstElement(&pList);
00510 return HashConstIterator<K,I,H>(pElement,pList,this);
00511 }
00512
00513
00514 }
00515
00516 #endif