00001
00002
00003
00004
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
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
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
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
00583
00584
00585
00586 Size size_;
00587
00588
00589
00590 Size capacity_;
00591
00592
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
00715
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
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
00740
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
00761 HashSet<Key> tmp;
00762 ConstIterator it = begin();
00763
00764
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
00781 HashSet<Key> tmp;
00782 ConstIterator it = begin();
00783
00784
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
00801
00802 if (this == &hash_set)
00803 {
00804 clear();
00805 }
00806 else
00807 {
00808
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 , 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
00979
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
00985 prev->next = pos.getTraits().position_->next;
00986 }
00987 else
00988 {
00989 throw Exception::InvalidIterator(__FILE__, __LINE__);
00990 }
00991 }
00992
00993
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
01021 return;
01022 }
01023
01024
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
01033 continue;
01034 }
01035
01036
01037 if ((bucket == f.getTraits().bucket_) && (bucket_[bucket] != f.getTraits().position_))
01038 {
01039
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
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
01060
01061 if (n != 0)
01062 {
01063
01064 next = n->next;
01065 n->next = 0;
01066
01067
01068 for (n = next; n != 0; n = next)
01069 {
01070 next = n->next;
01071 deleteNode_(n);
01072 no_deletions++;
01073 }
01074 }
01075 }
01076 }
01077
01078 else if (bucket < last_bucket)
01079 {
01080
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
01093
01094
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
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
01307 rehash();
01308
01309
01310 vector<Node*> old_buckets(bucket_);
01311
01312
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
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 }
01336
01337 #endif // BALL_DATATYPE_HASHSET_H