hashSet.h

Go to the documentation of this file.
00001 // -*- Mode: C++; tab-width: 2; -*-
00002 // vi: set ts=2:
00003 //
00004 // $Id: hashSet.h,v 1.43 2004/04/22 10:08:19 oliver Exp $ 
00005 //
00006 
00007 #ifndef BALL_DATATYPE_HASHSET_H
00008 #define BALL_DATATYPE_HASHSET_H
00009 
00010 #ifndef BALL_COMMON_H
00011 # include <BALL/common.h>
00012 #endif
00013 
00014 #ifndef BALL_COMMON_HASH_H
00015 # include <BALL/COMMON/hash.h>
00016 #endif
00017 
00018 #ifndef BALL_CONCEPT_FORWARDITERATOR_H
00019 # include <BALL/CONCEPT/forwardIterator.h>
00020 #endif
00021 
00022 #ifndef BALL_CONCEPT_VISITOR_H
00023 # include <BALL/CONCEPT/visitor.h>
00024 #endif
00025 
00026 #ifndef BALL_DATATYPE_FOREACH_H
00027 # include <BALL/DATATYPE/forEach.h>
00028 #endif
00029 
00030 #ifndef BALL_CONCEPT_PREDICATE_H
00031 # include <BALL/CONCEPT/predicate.h>
00032 #endif
00033 
00034 #ifndef BALL_CONCEPT_PROCESSOR_H
00035 # include <BALL/CONCEPT/processor.h>
00036 #endif
00037 
00038 #include <algorithm>
00039 
00040 
00041 namespace BALL
00042 {
00046   template <class Key>
00047   class HashSet
00048   {
00049     public:
00050 
00053     typedef Key ValueType;
00054       
00057     typedef Key KeyType;
00058 
00061     typedef Key* PointerType;
00062 
00063     // --- EXTERNAL ITERATORS
00064     struct Node
00065     {
00066       Node*       next;
00067       ValueType   value;
00068 
00069       Node(const KeyType& my_key, const Node* my_next)
00070         : next(const_cast<Node*>(my_next)),
00071           value(const_cast<ValueType&>(my_key))
00072       {
00073       }
00074     };
00075 
00076     typedef Node* IteratorPosition;
00077   
00078     class IteratorTraits
00079     {
00080 
00081       friend class HashSet<Key>;
00082       public:
00083 
00084       IteratorTraits()
00085         : bound_(0),
00086           position_(0),
00087           bucket_(0)
00088       {
00089       }
00090       
00091       IteratorTraits(const HashSet& hash_set)
00092         : bound_(const_cast<HashSet*>(&hash_set)),
00093           position_(0),
00094           bucket_(0)
00095       {
00096       }
00097       
00098       IteratorTraits(const IteratorTraits& traits)
00099         : bound_(traits.bound_),
00100           position_(traits.position_),
00101           bucket_(traits.bucket_)
00102       {
00103       }
00104       
00105       IteratorTraits& operator = (const IteratorTraits& traits)
00106       {
00107         bound_ = traits.bound_;
00108         position_ = traits.position_;
00109         bucket_ = traits.bucket_;
00110     
00111         return *this;
00112       }
00113 
00114       HashSet* getContainer()
00115       {
00116         return bound_;
00117       }
00118       
00119       const HashSet* getContainer() const
00120       {
00121         return bound_;
00122       }
00123       
00124       bool isSingular() const
00125       {
00126         return (bound_ == 0);
00127       }
00128       
00129       IteratorPosition& getPosition()
00130       {
00131         return position_;
00132       }
00133 
00134       const IteratorPosition& getPosition() const
00135       {
00136         return position_;
00137       }
00138 
00139       bool operator == (const IteratorTraits& traits) const
00140       {
00141         return (position_ == traits.position_);
00142       }
00143 
00144       bool operator != (const IteratorTraits& traits) const
00145       {
00146         return (position_ != traits.position_);
00147       }
00148       
00149       bool isValid() const
00150       {
00151         return ((bound_ != 0) && (position_ != 0)
00152                       && (bucket_ < (Position)bound_->bucket_.size()));
00153       }
00154 
00155       void invalidate()
00156       {
00157         bound_ = 0;
00158         position_ = 0;
00159         bucket_ = INVALID_POSITION;
00160       }
00161       
00162       void toBegin()
00163       {
00164         for (bucket_ = 0;  bucket_ < (Position)bound_->bucket_.size();  ++bucket_)
00165         {
00166           position_ = bound_->bucket_[bucket_];
00167 
00168           if (position_ != 0)
00169           {
00170             return;
00171           }
00172         }
00173       }
00174 
00175       bool isBegin() const
00176       {
00177         for (Position bucket = 0; bucket < (Position)bound_->bucket_.size();  ++bucket)
00178         {
00179           if (bound_->bucket_[bucket_] != 0)
00180           {
00181             if (position_ == bound_->bucket_[bucket_])
00182             {
00183               return true;
00184             } 
00185             else 
00186             {
00187               return false;
00188             }
00189           }
00190         }
00191 
00192         return false;
00193       }
00194 
00195       void toEnd()
00196       {
00197         position_ = 0;
00198       }
00199       
00200       bool isEnd() const
00201       {
00202         return (position_ == 0);
00203       }
00204       
00205       ValueType& getData()
00206       {
00207         return position_->value;
00208       }
00209 
00210       const ValueType& getData() const
00211       {
00212         return position_->value;
00213       }
00214 
00215       void forward()
00216       {
00217         position_ = position_->next;
00218 
00219         if (position_ != 0)
00220         {
00221           return;
00222         }
00223 
00224         for (++bucket_;  bucket_ < (Position)bound_->bucket_.size();  ++bucket_)
00225         {
00226           position_ = bound_->bucket_[bucket_];
00227 
00228           if (position_ != 0)
00229           {
00230             return;
00231           }
00232         }
00233       } 
00234 
00235       protected:
00236 
00237       HashSet*            bound_;
00238       IteratorPosition    position_;
00239       Position            bucket_;
00240     };
00241     friend class IteratorTraits;
00242 
00246 
00247     enum
00248     {
00250       INITIAL_CAPACITY          = 4,
00252       INITIAL_NUMBER_OF_BUCKETS = 3
00253     };
00254 
00256 
00260 
00265     class IllegalKey
00266       : public Exception::GeneralException
00267     {
00268       public:
00269       IllegalKey(const char* file, int line)
00270         : Exception::GeneralException(file, line)
00271       {
00272       }
00273     };
00274 
00276 
00280       
00282     typedef ForwardIterator<HashSet<Key>, ValueType, PointerType, IteratorTraits> Iterator;
00283 
00285     typedef ConstForwardIterator <HashSet<Key>, ValueType, PointerType, IteratorTraits> ConstIterator;
00286 
00287     // STL compatibility stuff
00289     typedef Iterator iterator;
00291     typedef ConstIterator const_iterator;
00293     typedef Key         value_type;
00295     typedef Key         key_type;
00297     typedef Key*        pointer;
00299     typedef const Key*  const_pointer;
00301     typedef Key&        reference;
00303     typedef const Key&  const_reference;
00305     typedef Size        size_type;
00307     typedef Index       difference_type;      
00309 
00313 
00316     HashSet(Size initial_capacity = INITIAL_CAPACITY, Size number_of_buckets = INITIAL_NUMBER_OF_BUCKETS);
00317       
00320     HashSet(const HashSet& hash_set);
00321 
00324     virtual ~HashSet()
00325     {
00326       destroy();
00327       deleteBuckets_();
00328     }
00329 
00334     virtual void clear();
00335   
00341     void destroy();
00342 
00344 
00348 
00352     void set(const HashSet& hash_set);
00353 
00357     const HashSet& operator = (const HashSet& rhs);
00358 
00362     void get(HashSet& hash_set) const;
00363 
00366     void swap(HashSet& hash_set);
00367 
00369 
00373 
00376     Size getBucketSize() const;
00377 
00380     Size getCapacity() const;
00381 
00384     Size getSize() const;
00385       
00388     Size size() const;
00389 
00392     Iterator find(const Key& key);
00393   
00396     ConstIterator find(const Key& key) const;
00397 
00400     std::pair<Iterator, bool> insert(const ValueType& item);
00401 
00405     Iterator insert(Iterator pos, const ValueType& item);
00406 
00410     Size erase(const KeyType& key);
00411 
00415     void erase(Iterator pos) throw(Exception::IncompatibleIterators, Exception::InvalidIterator);
00416 
00420     void erase(Iterator f, Iterator l) throw(Exception::IncompatibleIterators);
00421 
00423 
00431     const HashSet& operator &= (const HashSet& rhs);
00432     
00437     const HashSet& operator |= (const HashSet& rhs);
00438     
00443     HashSet operator & (const HashSet& rhs) const;
00444     
00449     HashSet operator | (const HashSet& rhs) const;
00450 
00454     HashSet operator + (const HashSet& rhs) const;
00455 
00461     HashSet operator - (const HashSet& rhs) const;
00462 
00466     const HashSet& operator += (const HashSet& rhs);
00467 
00471     const HashSet& operator -= (const HashSet& rhs);
00473 
00477 
00480     virtual void host(Visitor<HashSet<Key> >& visitor);
00482 
00486 
00489     bool has(const Key& key) const;
00490 
00493     bool isEmpty() const;
00494 
00497     bool operator == (const HashSet& hash_set) const;
00498 
00501     bool operator != (const HashSet& hash_set) const;
00503 
00507 
00512     bool isValid() const;
00513 
00516     virtual void dump(std::ostream& s = std::cout, Size depth = 0) const;
00517 
00519 
00520     // --- INTERNAL ITERATORS
00521 
00528     bool apply(UnaryProcessor<ValueType>& processor);
00530 
00531 
00532 
00535     Iterator begin()
00536     {
00537       return Iterator::begin(*this);
00538     }
00539 
00542     Iterator end()
00543     {
00544       return Iterator::end(*this);
00545     }
00546 
00549     ConstIterator begin() const
00550     {
00551       return ConstIterator::begin(*this);
00552     }
00553 
00556     ConstIterator end() const
00557     {
00558       return ConstIterator::end(*this);
00559     }
00560 
00561 
00562     protected:
00563 
00564     virtual Node* newNode_(const ValueType& value, Node* next) const;
00565 
00566     virtual void deleteNode_(Node* node) const;
00567   
00568     virtual HashIndex hash(const Key& key) const;
00569 
00570     virtual bool needRehashing_() const;
00571 
00572     virtual void rehash();
00573 
00574     private:
00575 
00576     void deleteBuckets_();
00577 
00578     Position hashBucket_(const Key& key) const;
00579 
00580     void rehash_();
00581 
00582     // --- ATTRIBUTES
00583 
00584     /*_ The number of elements in the hash set
00585     */
00586     Size  size_;
00587 
00588     /*_ The capacity - usually the number of buckets
00589     */
00590     Size  capacity_;
00591 
00592     /*_ Buckets are stored as a vector of linked lists of Nodes 
00593     */
00594     vector<Node*> bucket_;
00595   };
00596 
00597 
00598   template <class Key>
00599   HashSet<Key>::HashSet(Size initial_capacity, Size number_of_buckets)
00600     : size_(0),
00601       capacity_(initial_capacity),
00602       bucket_(number_of_buckets)
00603   {
00604     for (Position bucket = 0; bucket < (Position)bucket_.size(); ++bucket)
00605     {
00606       bucket_[bucket] = 0;
00607     }
00608   }
00609 
00610   template <class Key>
00611   HashSet<Key>::HashSet(const HashSet& hash_set)
00612     : size_(hash_set.size_),
00613       capacity_(hash_set.capacity_),
00614       bucket_(hash_set.bucket_.size())
00615   {
00616     Node* item = 0;
00617     
00618     for (Position bucket = 0; bucket < (Position)bucket_.size(); ++bucket)
00619     {
00620       bucket_[bucket] = 0;
00621 
00622       for (item = hash_set.bucket_[bucket]; item != 0; item = item->next)
00623       {
00624         bucket_[bucket] = newNode_(item->value, bucket_[bucket]);
00625       }
00626     }
00627   }
00628 
00629   template <class Key>
00630   void HashSet<Key>::set(const HashSet& hash_set)
00631   {
00632     if (&hash_set == this)
00633     {
00634       return;
00635     }
00636 
00637     destroy();
00638     
00639     deleteBuckets_();
00640 
00641     size_ = hash_set.size_;
00642     capacity_ = hash_set.capacity_;
00643     bucket_.resize(hash_set.bucket_.size());
00644 
00645     Node* item = 0;
00646     
00647     for (Position bucket = 0; bucket < (Position)bucket_.size(); ++bucket)
00648     {
00649       bucket_[bucket] = 0;
00650 
00651       for (item = hash_set.bucket_[bucket]; item != 0; item = item->next)
00652       {
00653         bucket_[bucket] = newNode_(item->value, bucket_[bucket]);
00654       }
00655     }
00656   }
00657 
00658   template <class Key>
00659   void HashSet<Key>::clear()
00660   {
00661     Node* node = 0;
00662     Node* next_node = 0;
00663     
00664     for (Position bucket = 0; bucket < (Position)bucket_.size(); ++bucket)
00665     {
00666       for (node = bucket_[bucket]; node != 0; node = next_node)
00667       {
00668         next_node = node->next;
00669         deleteNode_(node);
00670       }
00671       
00672       bucket_[bucket] = 0;
00673     }
00674 
00675     size_ = 0;
00676   }
00677 
00678   template <class Key>
00679   BALL_INLINE 
00680   void HashSet<Key>::destroy()
00681   {
00682     clear();
00683   }
00684 
00685   template <class Key>
00686   BALL_INLINE 
00687   const HashSet<Key>& HashSet<Key>::operator = (const HashSet& hash_set)
00688   {
00689     set(hash_set);
00690     return *this;
00691   }
00692 
00693   template <class Key>
00694   BALL_INLINE 
00695   void HashSet<Key>::get(HashSet& hash_set) const
00696 
00697   {
00698     hash_set.set(*this);
00699   }
00700 
00701   template <class Key>
00702   BALL_INLINE 
00703   void HashSet<Key>::swap(HashSet& hash_set)
00704   {
00705     std::swap(size_, hash_set.size_);
00706     std::swap(capacity_, hash_set.capacity_);
00707     std::swap(bucket_, hash_set.bucket_);
00708   }
00709 
00710   template <class Key>
00711   BALL_INLINE 
00712   const HashSet<Key>& HashSet<Key>::operator &= (const HashSet& rhs)
00713   {
00714     // Store all elements that are not part of the intersection
00715     // in a list for subsequent deletion.
00716     std::list<Key> erase_list;
00717     for (Iterator it = begin(); it != end(); ++it)
00718     {
00719       if (!rhs.has(*it))
00720       {
00721         erase_list.push_back(*it);
00722       }
00723     }
00724 
00725     // erase all elements not part of the intersection
00726     typename list<Key>::iterator list_it = erase_list.begin();
00727     for (; list_it != erase_list.end(); ++list_it)
00728     {
00729       erase(*list_it);
00730     }
00731 
00732     return *this;
00733   }
00734 
00735   template <class Key>
00736   BALL_INLINE 
00737   const HashSet<Key>& HashSet<Key>::operator |= (const HashSet<Key>& rhs)
00738   {
00739     // Compute the union of both sets by inserting every element of the
00740     // rhs set.
00741     for (ConstIterator it = rhs.begin(); it != rhs.end(); ++it)
00742     {
00743       insert(*it);
00744     }
00745 
00746     return *this;
00747   }
00748 
00749   template <class Key>
00750   BALL_INLINE 
00751   const HashSet<Key>& HashSet<Key>::operator += (const HashSet<Key>& rhs)
00752   {
00753     return operator |= (rhs);
00754   }
00755 
00756   template <class Key>
00757   BALL_INLINE 
00758   HashSet<Key> HashSet<Key>::operator & (const HashSet<Key>& rhs) const
00759   {
00760     // Create an empty hash set...
00761     HashSet<Key> tmp;
00762     ConstIterator it = begin();
00763     
00764     // ...and copy all the elements contained in the rhs hash set.
00765     for (; +it; ++it)
00766     {
00767       if (rhs.has(*it))
00768       {
00769         tmp.insert(*it);
00770       }
00771     }
00772 
00773     return tmp;
00774   }
00775 
00776   template <class Key>
00777   BALL_INLINE 
00778   HashSet<Key> HashSet<Key>::operator - (const HashSet<Key>& rhs) const
00779   {
00780     // Create an empty hash set...
00781     HashSet<Key> tmp;
00782     ConstIterator it = begin();
00783     
00784     // ...and copy all the elements contained in this set and not in the rhs hash set.
00785     for (; +it; ++it)
00786     {
00787       if (!rhs.has(*it))
00788       {
00789         tmp.insert(*it);
00790       }
00791     }
00792 
00793     return tmp;
00794   }
00795 
00796   template <class Key>
00797   BALL_INLINE 
00798   const HashSet<Key>& HashSet<Key>::operator -= (const HashSet<Key>& hash_set) 
00799   {
00800     // avoid memory corruption caused by iterating over freed space when
00801     // deleting myself
00802     if (this == &hash_set)
00803     {
00804       clear();
00805     }
00806     else
00807     {
00808       // erase all elements which are contained in this and hash_set 
00809       typename HashSet<Key>::ConstIterator it = hash_set.begin();
00810       for (; it != hash_set.end(); ++it)
00811       {
00812         if (has(*it))
00813         {
00814           erase(*it);
00815         }
00816       }
00817     }
00818     return *this;
00819   }
00820 
00821   template <class Key>
00822   BALL_INLINE 
00823   HashSet<Key> HashSet<Key>::operator | (const HashSet<Key>& rhs) const
00824   {
00825     HashSet<Key> tmp(*this);
00826     tmp |= rhs;
00827 
00828     return tmp;
00829   }
00830 
00831   template <class Key>
00832   BALL_INLINE 
00833   HashSet<Key> HashSet<Key>::operator + (const HashSet<Key>& rhs) const
00834   {
00835     return operator | (rhs);
00836   }
00837 
00838   template <class Key>
00839   BALL_INLINE 
00840   Size HashSet<Key>::getBucketSize() const
00841   {
00842     return (Size)bucket_.size();
00843   }
00844 
00845   template <class Key>
00846   BALL_INLINE 
00847   Size HashSet<Key>::getCapacity() const
00848   {
00849     return capacity_;
00850   }
00851 
00852   template <class Key>
00853   BALL_INLINE 
00854   Size HashSet<Key>::getSize() const
00855   {
00856     return size_;
00857   }
00858 
00859   template <class Key>
00860   BALL_INLINE 
00861   Size HashSet<Key>::size() const
00862   {
00863     return size_;
00864   }
00865 
00866   template <class Key>
00867   typename HashSet<Key>::Iterator HashSet<Key>::find(const Key& key)
00868   {
00869     Iterator it = end();
00870     Position bucket = hashBucket_(key);
00871     Node* node_ptr = bucket_[bucket];
00872     while (node_ptr != 0)
00873     {
00874       if (node_ptr->value == key)
00875       {
00876         it.getTraits().position_ = node_ptr;
00877         it.getTraits().bucket_ = bucket;
00878         break;
00879       }
00880       node_ptr = node_ptr->next;
00881     }
00882 
00883     return it;
00884   }
00885     
00886   template <class Key>
00887   BALL_INLINE 
00888   typename HashSet<Key>::ConstIterator HashSet<Key>::find(const Key& key) const
00889   {
00890     return (const_cast<HashSet*>(this))->find(key);
00891   }
00892 
00893   template <class Key>
00894   std::pair<typename HashSet<Key>::Iterator, bool> HashSet<Key>::insert
00895     (const ValueType& item)
00896   {
00897     Iterator it = find(item);
00898     if (it == end())
00899     {
00900       if (needRehashing_() == true)
00901       {
00902         rehash_();
00903       }
00904       
00905       Position bucket = hashBucket_(item);
00906 
00907       Node* next = bucket_[bucket];
00908       bucket_[bucket] = newNode_(item, next);
00909       
00910       ++size_;
00911       it.getTraits().position_ = bucket_[bucket];
00912       it.getTraits().bucket_ = bucket;
00913     }
00914 
00915     return std::pair<Iterator, bool>(it, true);
00916   }
00917 
00918   template <class Key>
00919   typename HashSet<Key>::Iterator HashSet<Key>::insert
00920     (typename HashSet<Key>::Iterator /* pos */, const ValueType& item)
00921   {
00922     return insert(item).first;
00923   }
00924 
00925   template <class Key>
00926   Size HashSet<Key>::erase(const KeyType& key)
00927   {
00928     Position  bucket = hashBucket_(key);
00929     Node*     previous = 0;
00930     Node*     node_ptr = bucket_[bucket];
00931     
00932     while (node_ptr != 0 && node_ptr->value != key)
00933     {
00934       previous = node_ptr;
00935       node_ptr = node_ptr->next;
00936     }
00937 
00938     if (node_ptr == 0)
00939     {
00940       return false;
00941     }
00942 
00943     if (node_ptr == bucket_[bucket])
00944     {
00945       bucket_[bucket] = node_ptr->next;
00946     } 
00947     else 
00948     {
00949       previous->next = node_ptr->next;
00950     }
00951 
00952     deleteNode_(node_ptr);
00953     --size_;
00954 
00955     return 1;
00956   }
00957 
00958   template <class Key>
00959   void HashSet<Key>::erase(Iterator pos)
00960     throw(Exception::IncompatibleIterators, Exception::InvalidIterator)
00961   {
00962     if (pos.getTraits().bound_ != this)
00963     {
00964       throw Exception::IncompatibleIterators(__FILE__, __LINE__);
00965     }
00966 
00967     if ((pos == end()) || (size_ == 0))
00968     {
00969       return;
00970     }
00971         
00972     if (pos.getTraits().position_ == bucket_[pos.getTraits().bucket_])
00973     {
00974       bucket_[pos.getTraits().bucket_] = pos.getTraits().position_->next;
00975     } 
00976     else 
00977     {
00978       // walk over all nodes in this bucket and identify the predecessor
00979       // of the node refered to by the iterator pos
00980       Node* prev = bucket_[pos.getTraits().bucket_];
00981       for (; (prev != 0) && (prev->next != pos.getTraits().position_); prev = prev->next) {};
00982       if (prev != 0)
00983       {
00984         // remove the node and reconnect the list
00985         prev->next = pos.getTraits().position_->next;
00986       }
00987       else 
00988       {
00989         throw Exception::InvalidIterator(__FILE__, __LINE__);
00990       }
00991     }
00992 
00993     // delete the node and decrement the set size
00994     deleteNode_(pos.getTraits().position_);
00995     --size_;
00996   }
00997 
00998   template <class Key>
00999   void HashSet<Key>::erase(Iterator f, Iterator l)
01000     throw(Exception::IncompatibleIterators)
01001   {
01002     if (f.getTraits().bound_ != this || l.getTraits().bound_ != this)
01003     {
01004       throw Exception::IncompatibleIterators(__FILE__, __LINE__);
01005     }
01006     
01007     if (f == end())
01008     {
01009       return;
01010     }
01011 
01012     Position last_bucket = l.getTraits().bucket_;
01013     if (l == end())
01014     {
01015       last_bucket = (Position)(bucket_.size() - 1);
01016     }
01017 
01018     if (f.getTraits().bucket_ > last_bucket)
01019     {
01020       // empty range - l < f
01021       return;
01022     }
01023 
01024     // count the deleted entries to correct the set size
01025     Size no_deletions = 0;
01026 
01027     Position bucket = f.getTraits().bucket_;
01028     for (; bucket <= last_bucket; bucket++)
01029     {
01030       if (bucket_[bucket] == 0)
01031       {
01032         // skip all empty buckets
01033         continue;
01034       }
01035 
01036 
01037       if ((bucket == f.getTraits().bucket_) && (bucket_[bucket] != f.getTraits().position_))
01038       {
01039         // find the predecessor of f
01040         Node* n = bucket_[bucket];
01041         Node* next;
01042         for (; (n->next != f.getTraits().position_) && (n->next != 0); n = n->next) {};
01043         
01044         if (bucket == last_bucket)
01045         {
01046           // delete everything from f to l in this bucket
01047 
01048           next = n->next;
01049           n->next = l.getTraits().position_;
01050           for (n = next; (n != 0) && (n != l.getTraits().position_); n = next)
01051           {
01052             next = n->next;
01053             deleteNode_(n);
01054             no_deletions++;
01055           }
01056         }
01057         else
01058         {
01059           // delete everything from f to the end in this bucket
01060 
01061           if (n != 0)
01062           {
01063             // mark the end of the list
01064             next = n->next;
01065             n->next = 0;
01066 
01067             // delete all remaining nodes
01068             for (n = next; n != 0; n = next)
01069             {
01070               next = n->next;
01071               deleteNode_(n);
01072               no_deletions++;
01073             }
01074           }
01075         }
01076       } 
01077       // if the current bucket lies between the first and the last bucket...
01078       else if (bucket < last_bucket)
01079       {
01080         // ...delete the whole bucket
01081         Node* next;
01082         for (Node* n = bucket_[bucket]; n != 0; n = next)
01083         {
01084           next = n->next;
01085           deleteNode_(n);
01086           no_deletions++;
01087         }
01088         bucket_[bucket] = 0;
01089       }
01090       else if (bucket == last_bucket)
01091       {
01092         // we delete everything in this bucket up to the iterator l
01093 
01094         // find the predecessor of l
01095         Node* n = bucket_[bucket];
01096         Node* next;
01097         for (; (n != 0) && (n != l.getTraits().position_); n = next)
01098         {
01099           next = n->next;
01100           deleteNode_(n);
01101           no_deletions++;
01102         }
01103 
01104         bucket_[bucket] = l.getTraits().position_;
01105       }
01106     }
01107 
01108     // correct the set size
01109     size_ -= no_deletions;
01110   }
01111 
01112   template <class Key>
01113   BALL_INLINE 
01114   void HashSet<Key>::host(Visitor<HashSet<Key> >& visitor)
01115   {
01116     visitor.visit(*this);
01117   }
01118     
01119   template <class Key>
01120   BALL_INLINE 
01121   bool HashSet<Key>::has(const Key& key) const  
01122   {
01123     return (find(key) != end());
01124   }
01125 
01126   template <class Key>
01127   BALL_INLINE 
01128   bool HashSet<Key>::isEmpty() const
01129   {
01130     return (size_ == 0);
01131   }
01132 
01133   template <class Key>
01134   bool HashSet<Key>::operator == (const HashSet& hash_set) const
01135   {
01136     if (size_ != hash_set.size_)
01137     {
01138       return false;
01139     }
01140 
01141     ConstIterator it1 = begin();
01142     ConstIterator it2 = hash_set.begin();
01143     while (it1 != end())
01144     {
01145       if (*it1 != *it2)
01146       {
01147         return false;
01148       }
01149       it1++;
01150       it2++;
01151     }
01152     return true;
01153   }
01154 
01155   template <class Key>
01156   BALL_INLINE
01157   bool HashSet<Key>::operator != (const HashSet& hash_set) const
01158   {
01159     return !(*this == hash_set);
01160   }
01161 
01162   template <class Key>
01163   bool HashSet<Key>::isValid() const
01164   {
01165     Size size = 0;
01166     Node* node = 0;
01167 
01168     for (Position bucket = 0; bucket < (Position)bucket_.size(); ++bucket)
01169     {
01170       for (node = bucket_[bucket]; node != 0; node = node->next)
01171       {
01172         ++size;
01173 
01174         if (node->next == 0)
01175         {
01176           break;
01177         }
01178       }
01179     }
01180 
01181     return (size_ == size);
01182   }      
01183 
01184   template <class Key>
01185   void HashSet<Key>::dump(std::ostream& s, Size depth) const
01186   {
01187     BALL_DUMP_STREAM_PREFIX(s);
01188 
01189     BALL_DUMP_DEPTH(s, depth);
01190 
01191     BALL_DUMP_DEPTH(s, depth);
01192     s << "  size: " << getSize() << std::endl;
01193 
01194     BALL_DUMP_DEPTH(s, depth);
01195     s << "  # buckets: " << getBucketSize() << std::endl;
01196 
01197     BALL_DUMP_DEPTH(s, depth);
01198     s << "  capacity: " << getCapacity() << std::endl;
01199 
01200     BALL_DUMP_DEPTH(s, depth);
01201     s << "  load factor: " << (float)size_ / (float)bucket_.size() << std::endl;
01202 
01203     for (Position bucket = 0; bucket < (Position)bucket_.size(); ++bucket)
01204     {
01205       BALL_DUMP_DEPTH(s, depth);
01206       s << "    bucket " << bucket << ": ";
01207       for (Node* ptr = bucket_[bucket]; ptr != 0; ptr = ptr->next)
01208       {
01209         s << "(" << (void*)ptr << ") ";
01210       }
01211       s << "(0)" << std::endl;
01212     }
01213 
01214     BALL_DUMP_STREAM_SUFFIX(s);
01215   } 
01216  
01217   template <class Key>
01218   bool HashSet<Key>::apply(UnaryProcessor<ValueType>& processor)
01219   {
01220     if (processor.start() == false)
01221     {
01222       return false;
01223     }
01224 
01225     Processor::Result result;
01226 
01227     Iterator it = begin();
01228     while (it != end())
01229     {
01230       result = processor(*it);
01231       if (result <= Processor::BREAK)
01232       {
01233         return (result == Processor::BREAK);
01234       }
01235       it++;
01236     }
01237 
01238     return processor.finish();
01239   }
01240 
01241   template <class Key>
01242   BALL_INLINE 
01243   HashIndex HashSet<Key>::hash(const Key& key) const
01244   {
01245     return (HashIndex)Hash(key);
01246   }
01247 
01248   template <class Key>
01249   BALL_INLINE 
01250   void HashSet<Key>::rehash()
01251   {
01252     capacity_ = (Size)getNextPrime((Size)bucket_.size() << 1);
01253   }
01254 
01255   template <class Key>
01256   void HashSet<Key>::deleteBuckets_()
01257   {
01258     Size i = 0;
01259     Node* node = 0;
01260     Node* next_node = 0;
01261     for (i = 0; i < bucket_.size(); i++)
01262     {
01263       node = bucket_[i];
01264       while (node != 0)
01265       {
01266         next_node = node->next;
01267         delete node;
01268         node = next_node;
01269       }
01270       bucket_[i] = 0;
01271     }
01272   }
01273 
01274   template <class Key>
01275   BALL_INLINE 
01276   typename HashSet<Key>::Node* HashSet<Key>::newNode_
01277     (const ValueType& value, typename HashSet<Key>::Node* next) const
01278   {
01279     return new Node(value, next);
01280   }
01281 
01282   template <class Key>
01283   BALL_INLINE 
01284   void HashSet<Key>::deleteNode_(typename HashSet<Key>::Node* node) const
01285   {
01286     delete node;
01287   }
01288 
01289   template <class Key>
01290   BALL_INLINE 
01291   bool HashSet<Key>::needRehashing_() const
01292   {
01293     return (size_ >= capacity_);
01294   }
01295 
01296   template <class Key>
01297   BALL_INLINE 
01298   HashIndex HashSet<Key>::hashBucket_(const Key& key) const
01299   {
01300     return (Position)((HashIndex)hash(key) % (HashIndex)bucket_.size());
01301   }
01302 
01303   template <class Key>
01304   void HashSet<Key>::rehash_()
01305   {
01306     // calculate the new number of buckets (in capacity_)
01307     rehash();
01308 
01309     // save the old contents
01310     vector<Node*> old_buckets(bucket_);
01311 
01312     // resize the bucket vector and initialize it with zero
01313     bucket_.clear();
01314     bucket_.resize(capacity_);
01315     Position i;
01316     for (i = 0; i < capacity_; i++)
01317     {
01318       bucket_[i] = 0;
01319     }
01320 
01321     // rehash the old contents into the new buckets
01322     Node* node;
01323     Node* next_node;
01324     for (Position i = 0; i < (Position)old_buckets.size(); ++i)
01325     {
01326       for (node = old_buckets[i]; node != 0; node = next_node)
01327       {
01328         next_node = node->next;
01329         Position new_bucket = hashBucket_(node->value);
01330         node->next = bucket_[new_bucket];
01331         bucket_[new_bucket] = node;
01332       }
01333     }
01334   }
01335 } // namespace BALL
01336 
01337 #endif // BALL_DATATYPE_HASHSET_H