00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #ifndef TEUCHOS_HASHSET_H
00030 #define TEUCHOS_HASHSET_H
00031
00036 #include "Teuchos_ConfigDefs.hpp"
00037 #include "Teuchos_Array.hpp"
00038 #include "Teuchos_HashUtils.hpp"
00039
00040 namespace Teuchos
00041 {
00042 using std::string;
00043
00044
00051 template<class Key> class HashSet
00052 {
00053 public:
00054
00056 inline HashSet(int capacity=101);
00057
00059 inline bool containsKey(const Key& key) const ;
00060
00062 inline void put(const Key& key);
00063
00065 inline void remove(const Key& key);
00066
00068 inline int size() const {return count_;}
00069
00071 inline Array<Key> arrayify() const ;
00072
00074 inline string toString() const ;
00075
00076 private:
00078 inline void rehash();
00080 inline int nextPrime(int newCap) const ;
00081
00082 Array<Array<Key> > data_;
00083 int count_;
00084 int capacity_;
00085 mutable Key mostRecentKey_;
00086 };
00087
00088
00092 template<class Key>
00093 ostream& operator<<(ostream& os, const HashSet<Key>& h);
00094
00095 template<class Key> inline
00096 string toString(const HashSet<Key>& h) {return h.toString();}
00097
00098
00099 template<class Key> inline
00100 HashSet<Key>::HashSet(int capacity)
00101 : data_(), count_(0), capacity_(HashUtils::nextPrime(capacity))
00102 {
00103 data_.resize(capacity_);
00104 }
00105
00106 template<class Key> inline
00107 bool HashSet<Key>::containsKey(const Key& key) const
00108 {
00109 const Array<Key>& candidates
00110 = data_[hashCode(key) % capacity_];
00111
00112 for (int i=0; i<candidates.length(); i++)
00113 {
00114 const Key& c = candidates[i];
00115 if (c == key)
00116 {
00117 return true;
00118 }
00119 }
00120 return false;
00121 }
00122
00123 template<class Key> inline
00124 void HashSet<Key>::put(const Key& key)
00125 {
00126 int index = hashCode(key) % capacity_;
00127
00128 Array<Key>& local = data_[index];
00129
00130
00131 for (int i=0; i<local.length(); i++)
00132 {
00133 if (local[i] == key)
00134 {
00135 return;
00136 }
00137 }
00138
00139
00140 count_++;
00141
00142
00143 if (count_ > capacity_)
00144 {
00145 capacity_ = HashUtils::nextPrime(capacity_+1);
00146 rehash();
00147
00148 index = hashCode(key) % capacity_;
00149 }
00150
00151 data_[index].append(key);
00152 }
00153
00154
00155
00156 template<class Key> inline
00157 void HashSet<Key>::rehash()
00158 {
00159 Array<Array<Key> > tmp(capacity_);
00160
00161 for (int i=0; i<data_.length(); i++)
00162 {
00163 for (int j=0; j<data_[i].length(); j++)
00164 {
00165 int newIndex = hashCode(data_[i][j]) % capacity_;
00166 tmp[newIndex].append(data_[i][j]);
00167 }
00168 }
00169
00170 data_ = tmp;
00171 }
00172
00173 template<class Key> inline
00174 Array<Key> HashSet<Key>::arrayify() const
00175 {
00176 Array<Key> rtn;
00177 rtn.reserve(size());
00178
00179 for (int i=0; i<data_.length(); i++)
00180 {
00181 for (int j=0; j<data_[i].length(); j++)
00182 {
00183 rtn.append(data_[i][j]);
00184 }
00185 }
00186
00187 return rtn;
00188 }
00189
00190 template<class Key> inline
00191 string HashSet<Key>::toString() const
00192 {
00193 string rtn = "HashSet[";
00194
00195 bool first = true;
00196
00197 for (int i=0; i<data_.length(); i++)
00198 {
00199 for (int j=0; j<data_[i].length(); j++)
00200 {
00201 if (!first) rtn += ", ";
00202 first = false;
00203 rtn += Teuchos::toString(data_[i][j]);
00204 }
00205 }
00206 rtn += "]";
00207 return rtn;
00208 }
00209
00210
00211 template<class Key> inline
00212 void HashSet<Key>::remove(const Key& key)
00213 {
00214 TEST_FOR_EXCEPTION(!containsKey(key),
00215 runtime_error,
00216 "HashSet<Key>::remove: key "
00217 << Teuchos::toString(key)
00218 << " not found in HashSet"
00219 << toString());
00220
00221 count_--;
00222 int h = hashCode(key) % capacity_;
00223 Array<Key>& candidates = data_[h];
00224
00225 for (int i=0; i<candidates.length(); i++)
00226 {
00227 if (candidates[i] == key)
00228 {
00229 candidates.remove(i);
00230 break;
00231 }
00232 }
00233 }
00234
00235
00236
00237 template<class Key> inline
00238 ostream& operator<<(ostream& os, const HashSet<Key>& h)
00239 {
00240 return os << h.toString();
00241 }
00242
00243
00244 }
00245
00246 #endif // TEUCHOS_HASHSET_H