BWAPI
|
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