BWAPI
SPAR/AIModule/BWTA/vendors/CGAL/CGAL/Arrangement_2/Open_hash.h
Go to the documentation of this file.
00001 // Copyright (c) 2005  Tel-Aviv University (Israel).
00002 // All rights reserved.
00003 //
00004 // This file is part of CGAL (www.cgal.org); you may redistribute it under
00005 // the terms of the Q Public License version 1.0.
00006 // See the file LICENSE.QPL distributed with CGAL.
00007 //
00008 // Licensees holding a valid commercial license may use this file in
00009 // accordance with the commercial license agreement provided with the software.
00010 //
00011 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00012 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00013 //
00014 // $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/CGAL-3.5-branch/Arrangement_on_surface_2/include/CGAL/Arrangement_2/Open_hash.h $
00015 // $Id: Open_hash.h 33290 2006-08-14 06:28:19Z wein $
00016 // 
00017 //
00018 // Author(s)     : Ron Wein          <wein@post.tau.ac.il>
00019 #ifndef CGAL_OPEN_HASH_H
00020 #define CGAL_OPEN_HASH_H
00021 
00026 #include <vector>
00027 #include <list>
00028 
00029 CGAL_BEGIN_NAMESPACE
00030 
00035 template <class Type>
00036 class Default_is_equal_functor
00037 {
00038 public:
00039 
00040   bool operator() (const Type& t1, const Type& t2) const
00041   {
00042     return (t1 == t2);
00043   }
00044 };
00045 
00049 template <class Key_,
00050           class Hash_functor_,
00051           class EqualKey_ = Default_is_equal_functor<Key_> >
00052 class Open_hash
00053 {
00054 public:
00055 
00056   // Type definitions (for STL compatibility):
00057   typedef Key_               value_type;
00058   typedef Key_               key_type;
00059   typedef Hash_functor_      hasher;
00060   typedef EqualKey_          key_equal;
00061   typedef value_type*        pointer;
00062   typedef value_type&        reference;
00063   typedef const value_type*  const_pointer;
00064   typedef const value_type&  const_reference;
00065   typedef size_t             size_type;
00066   typedef size_t             difference_type;
00067 
00068 protected:
00069 
00070   enum
00071   {
00072     DEFAULT_NUMBER_OF_BUCKETS = 1000
00073   };
00074 
00075   typedef std::list<Key_>                  Bucket;
00076   typedef typename Bucket::iterator        Bucket_iterator;
00077   typedef typename Bucket::const_iterator  Bucket_const_iterator;
00078   
00079   size_type            n_buckets;   // Number of buckets in the hash.
00080   size_type            n_objects;   // Number of objects stored in the hash.
00081   std::vector<Bucket>  buckets;     // The buckets (linked lists of objects).
00082   hasher               hash_func;   // The hashing functor.
00083   key_equal            equal_func;  // The equality functor.
00084 
00085 private:
00086 
00087   // Copy constructor and assignment operator - not supported.
00088   Open_hash (const Open_hash& );
00089   Open_hash& operator= (const Open_hash& );
00090 
00091 public:
00092 
00094 
00095 
00097   Open_hash () :
00098     n_objects (0),
00099     buckets (DEFAULT_NUMBER_OF_BUCKETS),
00100     hash_func (),
00101     equal_func ()
00102   {
00103     n_buckets = buckets.size();
00104   }
00105 
00107   Open_hash (size_type n,
00108              hasher hash_f = hasher(),
00109              key_equal equal_f = key_equal()) :
00110     n_objects (0),
00111     buckets (n),
00112     hash_func (hash_f),
00113     equal_func (equal_f)
00114   {
00115     n_buckets = buckets.size();
00116   }
00117 
00119   virtual ~Open_hash ()
00120   {}
00122 
00124 
00125 
00127   size_type bucket_count () const
00128   {
00129     return (n_buckets);
00130   }
00131 
00133   size_type size () const
00134   {
00135     return (n_objects);
00136   }
00137 
00139   bool empty () const
00140   {
00141     return (n_objects == 0);
00142   }
00143 
00145   const hasher& hash_funct () const
00146   {
00147     return (hash_func);
00148   }
00149 
00151   const key_equal& key_eq () const
00152   {
00153     return (equal_func);
00154   }
00156 
00160   class iterator
00161   {
00162     friend class Open_hash<Key_, Hash_functor_, EqualKey_>;
00163 
00164   private:
00165   
00166     Open_hash<Key_, Hash_functor_, EqualKey_>  *p_hash;  // The scanned hash.
00167     int                           index;  // The index of the current bucket.
00168     Bucket_iterator               iter;   // Iterator for the current bucket.
00169 
00171     iterator (const Open_hash<Key_, Hash_functor_, EqualKey_>& hash,
00172               size_type ind) :
00173       p_hash (const_cast<Open_hash<Key_,Hash_functor_,EqualKey_>* >(&hash))
00174     {
00175       // Find the next non-empty bucket and get an iterator for it.
00176       index = p_hash->_next_non_empty_bucket (static_cast<int> (ind));
00177 
00178       if (index < static_cast<int>(p_hash->n_buckets))
00179         iter = (p_hash->buckets[index]).begin();
00180     }
00181 
00183     iterator (const Open_hash<Key_, Hash_functor_, EqualKey_>& hash,
00184               size_type ind,
00185               Bucket_iterator it) :
00186       p_hash (const_cast<Open_hash<Key_,Hash_functor_,EqualKey_>* >(&hash)),
00187       index (static_cast<int> (ind)),
00188       iter (it)
00189     {}
00190 
00191   public:
00192 
00194     iterator () :
00195       p_hash (NULL),
00196       index (0)
00197     {}
00198 
00200     bool operator== (const iterator& it)
00201     {
00202       if (p_hash != it.p_hash)
00203         return (false);
00204       
00205       if (p_hash == NULL)
00206         return (true);
00207 
00208       if ((index < 0 || index >= static_cast<int>(p_hash->n_buckets)) &&
00209           (it.index < 0 || it.index >= static_cast<int>(p_hash->n_buckets)))
00210         return (true);
00211 
00212       return (index == it.index && iter == it.iter);
00213     }
00214 
00216     bool operator!= (const iterator& it)
00217     {
00218       return (! (*this == it));
00219     }
00220 
00222     const_reference operator* () const
00223     {
00224       CGAL_precondition (p_hash != NULL &&
00225                          index >= 0 && index < static_cast<int>(p_hash->n_buckets));
00226 
00227       return (*iter);
00228     }
00229 
00231     const_pointer operator-> () const
00232     {
00233       CGAL_precondition (p_hash != NULL &&
00234                          index >= 0 && index < static_cast<int>(p_hash->n_buckets));
00235 
00236       return (&(*iter));
00237     }
00238 
00239     /* Increment the iterator (prefix notation). */
00240     iterator& operator++ ()
00241     {
00242       // Check end conditions.
00243       CGAL_precondition (p_hash != NULL);
00244 
00245       if (index >= static_cast<int>(p_hash->n_buckets))
00246         return (*this);
00247 
00248       if (index < 0)
00249       {
00250         // Find the first non-empty bucket and get an iterator for it.
00251         index = p_hash->_next_non_empty_bucket (0);
00252 
00253         if (index < static_cast<int>(p_hash->n_buckets))
00254           iter = (p_hash->buckets[index]).begin();
00255 
00256         return (*this);
00257       }
00258       
00259       // Try to increment the current list iterator.
00260       ++iter;
00261 
00262       if (iter == (p_hash->buckets[index]).end())
00263       {
00264         // Find the next non-empty bucket and get an iterator for it.
00265         index = p_hash->_next_non_empty_bucket (index + 1);
00266 
00267         if (index < static_cast<int>(p_hash->n_buckets))
00268           iter = (p_hash->buckets[index]).begin();
00269       }
00270         
00271       return (*this);
00272     }
00273 
00274     /* Increment the iterator (postfix notation). */
00275     iterator operator++ (int )
00276     {
00277       iterator   temp = *this;
00278 
00279       ++(*this);
00280       return (temp);
00281     }
00282 
00283     /* Decrement the iterator (prefix notation). */
00284     iterator& operator-- ()
00285     {
00286       // Check end conditions.
00287       CGAL_precondition (p_hash != NULL);
00288 
00289       if (index >= static_cast<int>(p_hash->n_buckets))
00290       {
00291         // Find the last non-empty bucket and get an iterator for it.
00292         index = p_hash->_prev_non_empty_bucket 
00293                            (static_cast<int>(p_hash->n_buckets) - 1);
00294 
00295         if (index >= 0)
00296         {
00297           iter = (p_hash->buckets[index]).end();
00298           --iter;
00299         }
00300 
00301         return (*this);
00302       }
00303 
00304       if (index < 0)
00305         return (*this);
00306       
00307       // Try to decrement the current list iterator.
00308       if (iter != (p_hash->buckets[index]).begin())
00309       {
00310         --iter;
00311       }
00312       else
00313       {
00314         // Find the nprevious non-empty bucket and get an iterator for it.
00315         index = p_hash->_prev_non_empty_bucket (index - 1);
00316 
00317         if (index >= 0)
00318         {
00319           iter = (p_hash->buckets[index]).end();
00320           --iter;
00321         }
00322       }
00323         
00324       return (*this);
00325     }
00326 
00327     /* Decrement the iterator (postfix notation). */
00328     iterator operator-- (int )
00329     {
00330       iterator   temp = *this;
00331 
00332       --(*this);
00333       return (temp);
00334     }
00335 
00336   };
00337 
00338   friend class iterator;
00339 
00341 
00342 
00344   iterator begin () const
00345   {
00346     return (iterator (*this, 0));
00347   }
00348 
00350   iterator end () const
00351   {
00352     return (iterator (*this, n_buckets));
00353   }
00354 
00356 
00358 
00359 
00366   iterator find (const key_type& key) const
00367   {
00368     // Look for the object in the approriate bucket.
00369     const size_type           index = hash_func (key) % n_buckets;
00370     Bucket&                   my_bucket = const_cast<Bucket&>(buckets[index]);
00371     Bucket_iterator           bucket_it = _find_in_bucket (index, key);
00372 
00373     if (bucket_it == my_bucket.end())
00374       // The object was not found.
00375       return (end());
00376 
00377     // Create an iterator pointing to the object.
00378     return (iterator (*this, index, bucket_it));
00379   }
00380 
00388   std::pair<iterator,bool> insert (const value_type& val)
00389   {
00390     // Look for the object in the approriate bucket.
00391     const size_type           index = hash_func (val) % n_buckets;
00392     Bucket_iterator           bucket_it = _find_in_bucket (index, val);
00393     std::pair<iterator,bool>  res;
00394 
00395     // Check if the object already exists.
00396     if (bucket_it != buckets[index].end())
00397     {
00398       // In case the object already exists:
00399       res.first = iterator (*this, index, bucket_it);
00400       res.second = false;
00401     }
00402     else
00403     {
00404       // Insert a new object to the approriate bucket.
00405       buckets[index].push_front (val);
00406 
00407       n_objects++;
00408 
00409       res.first = iterator (*this, index, buckets[index].begin());
00410       res.second = true;
00411     }
00412       
00413     return (res);
00414   }
00415 
00420   void erase (iterator pos)
00421   {
00422     // Erase the object from the approriate bucket.
00423     CGAL_precondition (pos.p_hash == this);
00424 
00425     const int        index = pos.index;
00426     Bucket_iterator  bucket_it = pos.iter;
00427 
00428     CGAL_assertion (index >= 0 && index < static_cast<int>(n_buckets));
00429     
00430     buckets[index].erase (bucket_it);
00431     n_objects--;
00432 
00433     return;
00434   }
00435 
00441   bool erase (const key_type& key)
00442   {
00443     // Look for the object in the approriate bucket.
00444     const size_type           index = hash_func (key) % n_buckets;
00445     Bucket_iterator           bucket_it = _find_in_bucket (index, key);
00446 
00447     if (bucket_it == buckets[index].end())
00448       // The object was not found.
00449       return (false);
00450 
00451     // Erase the object from the approriate bucket.
00452     buckets[index].erase (bucket_it);
00453     n_objects--;
00454 
00455     return (true);
00456   }
00457 
00461   void clear ()
00462   {
00463     // Clear all buckets.
00464     typename std::vector<Bucket>::iterator  it;
00465 
00466     for (it = buckets.begin(); it != buckets.end(); ++it)
00467       (*it).clear();
00468 
00469     n_objects = 0;
00470     return;
00471   }
00473 
00475 
00476 
00482   void resize (size_type n)
00483   {
00484     rehash (n, hash_func);
00485   };
00486 
00491   void rehash (size_type n, hasher hash_f)
00492   {
00493     // Set the hashing functor.
00494     hash_func = hash_f;
00495 
00496     // Rehash the structure.
00497     std::vector<Bucket>                     new_buckets (n);
00498     typename std::vector<Bucket>::iterator  it;
00499     Bucket_iterator                         bucket_it;
00500     size_type                               index;
00501 
00502     for (it = buckets.begin(); it != buckets.end(); ++it)
00503     {
00504       for (bucket_it = (*it).begin(); bucket_it != (*it).end(); ++bucket_it)
00505       {
00506         const value_type&  val = *bucket_it;
00507         
00508         index = hash_func (val) % n;
00509         new_buckets[index].push_back (val);
00510       }
00511     }
00512 
00513     // Set the new buckets.
00514     buckets = new_buckets;
00515     n_buckets = n;
00516 
00517     return;
00518   }
00520 
00521 private:
00522 
00524   int _prev_non_empty_bucket (int index) const
00525   {
00526     while (index >= 0 && buckets[index].empty())
00527       index--;
00528 
00529     return (index);
00530   }
00531 
00533   int _next_non_empty_bucket (int index) const
00534   {
00535     while (index < static_cast<int>(n_buckets) && buckets[index].empty())
00536       index++;
00537 
00538     return (index);
00539   }
00540 
00542   Bucket_iterator _find_in_bucket (int index,
00543                                    const value_type& val) const
00544   {
00545     Bucket&             my_bucket = const_cast<Bucket&>(buckets[index]);
00546     Bucket_iterator     iter = my_bucket.begin();
00547 
00548     while (iter != my_bucket.end() && ! equal_func (val, *iter))
00549       ++iter;
00550 
00551     return (iter);
00552   }
00553 };
00554 
00558 template <class Key_, class Data_,
00559           class Hash_functor_,
00560           class EqualKey_ = Default_is_equal_functor<Key_> >
00561 class Hash_map
00562 {
00563 public:
00564 
00565   // Type definitions (for STL compatibility):
00566   typedef Key_                   key_type;
00567   typedef Data_                  data_type;
00568   typedef std::pair<Key_,Data_>  value_type;
00569   typedef Hash_functor_          hasher;
00570   typedef EqualKey_              key_equal;
00571   typedef value_type*            pointer;
00572   typedef value_type&            reference;
00573   typedef const value_type&      const_reference;
00574   typedef size_t                 size_type;
00575   typedef size_t                 difference_type;
00576 
00577 protected:
00578 
00582   class Value_type_hash_functor
00583   {
00584   private:
00585 
00586     Hash_functor_       hash_func;
00587 
00588   public:
00589 
00590     Value_type_hash_functor () :
00591       hash_func ()
00592     {}
00593 
00594     Value_type_hash_functor (Hash_functor_ func) :
00595       hash_func (func)
00596     {}
00597 
00598     size_type operator() (const value_type& vt) const
00599     {
00600       return (hash_func (vt.first));
00601     }
00602   };
00603 
00607   class Value_type_equal
00608   {
00609   private:
00610 
00611     EqualKey_          equal_func;
00612 
00613   public:
00614 
00615     Value_type_equal () :
00616       equal_func ()
00617     {}
00618 
00619     Value_type_equal (EqualKey_ func) :
00620       equal_func (func)
00621     {}
00622 
00623     bool operator() (const value_type& vt1, const value_type& vt2) const
00624     {
00625       return (equal_func (vt1.first, vt2.first));
00626     }
00627   };
00628 
00629   typedef Open_hash<value_type, 
00630                     Value_type_hash_functor, Value_type_equal>    Hash;
00631 
00632   Value_type_hash_functor            vt_hash_func;
00633   Value_type_equal                   vt_equal_func;
00634   Hash                               hash;
00635 
00636 public:
00637 
00639 
00640 
00642   Hash_map () :
00643     vt_hash_func (hasher()),
00644     vt_equal_func (key_equal()),
00645     hash ()
00646   {}
00647 
00649   Hash_map (size_type n,
00650             hasher hash_f = hasher(),
00651             key_equal equal_f = key_equal()) :
00652     vt_hash_func (hash_f),
00653     vt_equal_func (equal_f),
00654     hash (n, vt_hash_func, vt_equal_func)
00655   {}
00656 
00658   virtual ~Hash_map ()
00659   {}
00661 
00663 
00664 
00666   size_type bucket_count () const
00667   {
00668     return (hash.bucket_count());
00669   }
00670 
00672   size_type size () const
00673   {
00674     return (hash.size());
00675   }
00676 
00678   bool empty () const
00679   {
00680     return (hash.empty());
00681   }
00683 
00684   typedef typename Hash::iterator    iterator;
00685 
00687 
00688 
00690   iterator begin () const
00691   {
00692     return (hash.begin());
00693   }
00694 
00696   iterator end () const
00697   {
00698     return (hash.end());
00699   }
00700 
00702 
00704 
00705 
00712   iterator find (const key_type& key) const
00713   {
00714     value_type    vt (key, data_type());
00715     return (hash.find (vt));
00716   }
00717 
00725   data_type& operator[] (const key_type& key)
00726   {
00727     value_type                  vt (key, data_type());
00728     std::pair<iterator, bool>   res = hash.insert (vt);
00729 
00730     return (const_cast<data_type&> ((*(res.first)).second));
00731   }
00732 
00740   std::pair<iterator,bool> insert (const value_type& val)
00741   {
00742     return (hash.insert (val));
00743   }
00744 
00749   void erase (iterator pos)
00750   {
00751     hash.erase (pos);
00752     return;
00753   }
00754 
00760   bool erase (const key_type& key)
00761   {
00762     value_type    vt (key, data_type());
00763     return (hash.erase (vt));
00764   }
00765 
00769   void clear ()
00770   {
00771     hash.clear();
00772   }
00774 
00776 
00777 
00783   void resize (size_type n)
00784   {
00785     hash.resize (n);
00786   };
00787 
00792   void rehash (size_type n, hasher hash_f)
00793   {
00794     vt_hash_func = Value_type_hash_functor (hash_f);
00795     hash.rehash (n, vt_hash_func);
00796   }
00798 
00799 };
00800 
00801 CGAL_END_NAMESPACE
00802 
00803 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines