Open
Graph Drawing
Framework

 v.2012.05
 

Hashing.h
Go to the documentation of this file.
00001 /*
00002  * $Revision: 2299 $
00003  * 
00004  * last checkin:
00005  *   $Author: gutwenger $ 
00006  *   $Date: 2012-05-07 15:57:08 +0200 (Mon, 07 May 2012) $ 
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     // destruction
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 // Hash function classes have to define
00234 // int hash(const E &key)
00235 //
00236 // "const E &" can be replaced by "E"
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     // destruction
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 } // end namespace ogdf
00515 
00516 #endif