hash_list.h
Go to the documentation of this file.00001 #ifndef hash_list_h_included
00002 #define hash_list_h_included
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
00030
00031
00032
00033 #include <list>
00034 #include <vector>
00035 #include <utility>
00036 #include <cxxtls/hashers.h>
00037
00038 namespace cxxtls
00039 {
00040
00044
00045
00046 template<class Key, class Value, class Hash=Hasher<Key> >
00047 class hash_list
00048
00122 {
00123 Value empty_value_;
00124
00125
00126 public:
00127
00128 typedef hash_list<Key,Value,Hash> self;
00129
00130 typedef typename std::pair<Key,Value> mapped_type;
00134
00135 struct value_type
00140
00141 {
00142 value_type *bucket_next_;
00143
00144 mapped_type data_;
00145
00146 value_type(value_type* bn, Key const &k, Value const &v)
00147 : bucket_next_(bn),
00148 data_(k,v)
00149 {
00156 }
00157
00158 };
00159
00160 typedef std::list<value_type> List;
00161 typedef std::vector<value_type*> Vector;
00162
00163 typedef typename List::iterator iterator;
00164 typedef typename List::const_iterator const_iterator;
00165
00166 private:
00167
00168 size_t size_;
00169 size_t average_chain_length_;
00170 List list_;
00171 Vector ht_;
00172 Hash hash;
00173
00174 public:
00175
00176 hash_list(int chain_length=10)
00177 : size_(0),
00178 average_chain_length_(chain_length),
00179 ht_(10)
00180
00183 {
00184 typename Vector::iterator first = ht_.begin();
00185 typename Vector::iterator last = ht_.end();
00186
00187 while(first != last)
00188 {
00189 *first = 0;
00190 ++first;
00191 }
00192
00193 }
00194
00195 ~hash_list()
00197 {
00198 }
00199
00200 size_t size() const { return size_; }
00201
00202 iterator begin() { return list_.begin(); }
00203 iterator end() { return list_.end(); }
00204
00205 const_iterator begin() const { return list_.begin(); }
00206 const_iterator end() const { return list_.end(); }
00207
00208 iterator insert(mapped_type const &data)
00217
00218 {
00219 list_.push_back( value_type(0, data.first, data.second) );
00220
00221 iterator last = end();
00222
00223 --last;
00224
00225
00226 value_type *p = & (*last);
00227
00228 int hash_code = hash(data.first);
00229
00230 hash_code %= ht_.size();
00231
00232 last->bucket_next_ = ht_[hash_code];
00233
00234 ht_[hash_code] = p;
00235
00236 ++size_;
00237
00238 if(size_ / ht_.size() > average_chain_length_)
00239 {
00240 resize();
00241 }
00242
00243 return last;
00244 }
00245
00246 void erase(iterator location)
00247
00248
00249
00250
00251
00252
00253
00254
00255 {
00256 value_type *p = &(*location);
00257
00258 int bucket = hash(p->data_.first) % ht_.size();
00259
00260 if(ht_[bucket] == p)
00261 {
00262
00263
00264 ht_[bucket] = p->bucket_next_;
00265
00266 }
00267 else
00268 {
00269
00270
00271 value_type *scan = ht_[bucket];
00272
00273 while(scan->bucket_next_)
00274 {
00275 if(scan->bucket_next_ == p)
00276 {
00277 scan->bucket_next_ = p->bucket_next_;
00278 break;
00279 }
00280
00281 scan = scan->bucket_next_;
00282
00283 }
00284
00285 }
00286
00287 list_.erase(location);
00288
00289 --size_;
00290
00291 }
00292
00293 iterator find(Key const &key)
00294
00295
00296
00297
00298 {
00299 int hash_code = hash(key);
00300
00301 hash_code %= ht_.size();
00302
00303 value_type* scan = ht_[hash_code];
00304
00305 while(scan)
00306 {
00307 if(scan->data_.first == key)
00308 {
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327 iterator rv;
00328
00329 char *p = (char*)scan;
00330
00331 p -= 2 * sizeof(void*);
00332
00333 char **x = (char **)&rv;
00334
00335 x[0] = p;
00336
00337 return rv;
00338 }
00339
00340 scan = scan->bucket_next_;
00341 }
00342
00343 return end();
00344
00345 }
00346
00347 const_iterator find( Key const &index ) const
00350 {
00351 self * me = (self*)(this);
00352
00353 return me->find(index);
00354
00355 }
00356
00357
00358 Value const &operator[] (Key const &index) const
00359
00367
00368 {
00369 const_iterator rv = find(index);
00370
00371 if(rv == end())
00372 return empty_value_;
00373
00374 return rv->data_.second;
00375 }
00376
00377 struct index_helper
00378
00435 {
00436 typedef hash_list<Key, Value, Hash> HL;
00437 Key const& key_;
00438 HL* list_;
00439
00440 index_helper(Key const& k, HL *l)
00441 : key_(k),
00442 list_(l)
00443 {
00445 }
00446
00447 operator Value const &()
00448
00456 {
00457 iterator ptr = list_->find(key_);
00458
00459 if(ptr == list_->end())
00460 return list_->empty_value_;
00461
00462 return ptr->data_.second;
00463
00464 }
00465
00466
00467 Value const &operator=( Value const &r )
00468
00475 {
00476
00477 iterator ptr = list_->find(key_);
00478
00479 if(ptr != list_->end())
00480 {
00481 list_->erase(ptr);
00482 }
00483
00484 list_->insert( mapped_type(key_,r) );
00485
00486 return r;
00487
00488
00489 }
00490
00491
00492 };
00493
00494 friend class index_helper;
00495
00496
00497 index_helper operator [] (Key const &index)
00500 {
00501
00502
00503
00504 return index_helper(index,this);
00505 }
00506
00507
00508
00509 private:
00510
00511 void resize()
00512 {
00516
00517 int new_size = size_ / average_chain_length_;
00518
00519 if(new_size < 10)
00520 new_size = 10;
00521
00522 Vector new_table( new_size );
00523
00524 while(new_table.size() != (unsigned)(new_size))
00525 {
00526 new_table.push_back(0);
00527 }
00528
00529 ht_.swap(new_table);
00530
00531
00532
00533
00534
00535 typename List::iterator f = list_.begin();
00536 typename List::iterator l = list_.end();
00537
00538 while(f != l)
00539 {
00540 value_type *cur = &(*f);
00541
00542 int hash_code = hash(cur->data_.first);
00543
00544 hash_code %= ht_.size();
00545
00546 cur->bucket_next_ = ht_[hash_code];
00547
00548 ht_[hash_code] = cur;
00549
00550 ++f;
00551 }
00552
00553
00554 }
00555 };
00556 }
00557 #endif