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