Fairport
v1.0.38
|
00001 00002 00003 00004 00005 00006 00007 00008 00009 00010 00011 00012 00015 00016 #ifndef FAIRPORT_UTIL_BTREE_H 00017 #define FAIRPORT_UTIL_BTREE_H 00018 00019 #include <iterator> 00020 #include <vector> 00021 #include <boost/iterator/iterator_facade.hpp> 00022 00023 #include "fairport/util/primitives.h" 00024 #include "fairport/util/errors.h" 00025 00026 #ifdef _MSC_VER 00027 #pragma warning(push) 00028 #pragma warning(disable:4250) 00029 #endif 00030 00031 namespace fairport 00032 { 00033 00034 template<typename K, typename V> 00035 struct btree_iter_impl; 00036 00037 template<typename K, typename V> 00038 class const_btree_node_iter; 00039 00040 template<typename K, typename V> 00041 class btree_node_nonleaf; 00042 00050 template<typename K, typename V> 00051 class btree_node 00052 { 00053 public: 00054 typedef const_btree_node_iter<K,V> const_iterator; 00055 00056 virtual ~btree_node() { } 00057 00064 virtual const V& lookup(const K& key) const = 0; 00065 00071 virtual const K& get_key(uint pos) const = 0; 00072 00077 virtual uint num_values() const = 0; 00078 00085 const_iterator begin() const 00086 { return const_iterator(this, false); } 00087 00093 const_iterator end() const 00094 { return const_iterator(this, true); } 00095 00099 int binary_search(const K& key) const; 00100 00101 protected: 00102 00103 // iter support 00104 friend class const_btree_node_iter<K,V>; 00105 friend class btree_node_nonleaf<K,V>; 00108 virtual void first(btree_iter_impl<K,V>& iter) const = 0; 00111 virtual void last(btree_iter_impl<K,V>& iter) const = 0; 00114 virtual void next(btree_iter_impl<K,V>& iter) const = 0; 00117 virtual void prev(btree_iter_impl<K,V>& iter) const = 0; 00118 }; 00119 00130 template<typename K, typename V> 00131 class btree_node_leaf : public virtual btree_node<K,V> 00132 { 00133 public: 00134 virtual ~btree_node_leaf() { } 00135 00140 const V& lookup(const K& key) const; 00141 00145 virtual const V& get_value(uint pos) const = 0; 00146 00147 protected: 00148 00149 // iter support 00150 friend class const_btree_node_iter<K,V>; 00151 void first(btree_iter_impl<K,V>& iter) const 00152 { iter.m_leaf = const_cast<btree_node_leaf<K,V>* >(this); iter.m_leaf_pos = 0; } 00153 void last(btree_iter_impl<K,V>& iter) const 00154 { iter.m_leaf = const_cast<btree_node_leaf<K,V>* >(this); iter.m_leaf_pos = this->num_values()-1; } 00155 void next(btree_iter_impl<K,V>& iter) const; 00156 void prev(btree_iter_impl<K,V>& iter) const; 00157 }; 00158 00170 template<typename K, typename V> 00171 class btree_node_nonleaf : public virtual btree_node<K,V> 00172 { 00173 public: 00174 virtual ~btree_node_nonleaf() { } 00175 00177 const V& lookup(const K& key) const; 00178 00179 protected: 00183 virtual btree_node<K,V>* get_child(uint i) = 0; 00187 virtual const btree_node<K,V>* get_child(uint i) const = 0; 00188 00189 // iter support 00190 friend class const_btree_node_iter<K,V>; 00191 friend class btree_node_leaf<K,V>; 00192 void first(btree_iter_impl<K,V>& iter) const; 00193 void last(btree_iter_impl<K,V>& iter) const; 00194 void next(btree_iter_impl<K,V>& iter) const; 00195 void prev(btree_iter_impl<K,V>& iter) const; 00196 }; 00197 00207 template<typename K, typename V> 00208 struct btree_iter_impl 00209 { 00210 btree_node_leaf<K,V>* m_leaf; 00211 uint m_leaf_pos; 00212 00213 std::vector<std::pair<btree_node_nonleaf<K,V>*, uint> > m_path; 00214 typedef typename std::vector<std::pair<btree_node_nonleaf<K,V>*, uint> >::iterator path_iter; 00215 }; 00216 00227 template<typename K, typename V> 00228 class const_btree_node_iter : public boost::iterator_facade<const_btree_node_iter<K,V>, const V, boost::bidirectional_traversal_tag> 00229 { 00230 public: 00232 const_btree_node_iter(); 00233 00237 const_btree_node_iter(const btree_node<K,V>* root, bool last); 00238 00239 private: 00240 friend class boost::iterator_core_access; 00241 00243 void increment() { m_impl.m_leaf->next(m_impl); } 00244 00247 bool equal(const const_btree_node_iter& other) const 00248 { return ((m_impl.m_leaf == other.m_impl.m_leaf) && (m_impl.m_leaf_pos == other.m_impl.m_leaf_pos)); } 00249 00252 const V& dereference() const 00253 { return m_impl.m_leaf->get_value(m_impl.m_leaf_pos); } 00254 00256 void decrement() { m_impl.m_leaf->prev(m_impl); } 00257 00258 mutable btree_iter_impl<K,V> m_impl; 00259 }; 00260 00261 } // end namespace 00262 00263 template<typename K, typename V> 00264 int fairport::btree_node<K,V>::binary_search(const K& k) const 00265 { 00266 uint end = num_values(); 00267 uint start = 0; 00268 uint mid = (start + end) / 2; 00269 00270 while(mid < end) 00271 { 00272 if(get_key(mid) < k) 00273 { 00274 start = mid + 1; 00275 } 00276 else if(get_key(mid) == k) 00277 { 00278 return mid; 00279 } 00280 else 00281 { 00282 end = mid; 00283 } 00284 00285 mid = (start + end) / 2; 00286 } 00287 00288 return mid - 1; 00289 } 00290 00291 template<typename K, typename V> 00292 const V& fairport::btree_node_leaf<K,V>::lookup(const K& k) const 00293 { 00294 int location = this->binary_search(k); 00295 00296 if(location == -1) 00297 throw key_not_found<K>(k); 00298 00299 if(this->get_key(location) != k) 00300 throw key_not_found<K>(k); 00301 00302 return get_value(location); 00303 } 00304 00305 template<typename K, typename V> 00306 void fairport::btree_node_leaf<K,V>::next(btree_iter_impl<K,V>& iter) const 00307 { 00308 if(++iter.m_leaf_pos == this->num_values()) 00309 { 00310 if(!iter.m_path.empty()) 00311 { 00312 for(typename btree_iter_impl<K,V>::path_iter piter = iter.m_path.begin(); 00313 piter != iter.m_path.end(); 00314 ++piter) 00315 { 00316 if((*piter).second + 1 < (*piter).first->num_values()) 00317 { 00318 // we're done with this leaf 00319 iter.m_leaf = NULL; 00320 00321 iter.m_path.back().first->next(iter); 00322 break; 00323 } 00324 } 00325 } 00326 } 00327 } 00328 00329 template<typename K, typename V> 00330 void fairport::btree_node_leaf<K,V>::prev(btree_iter_impl<K,V>& iter) const 00331 { 00332 if(iter.m_leaf_pos == 0) 00333 { 00334 if(!iter.m_path.empty()) 00335 { 00336 for(typename btree_iter_impl<K,V>::path_iter piter = iter.m_path.begin(); 00337 piter != iter.m_path.end(); 00338 ++piter) 00339 { 00340 // we're done with this leaf 00341 iter.m_leaf = NULL; 00342 00343 if((*piter).second != 0 && (*piter).first->num_values() > 1) 00344 { 00345 iter.m_path.back().first->prev(iter); 00346 break; 00347 } 00348 } 00349 } 00350 } 00351 else 00352 { 00353 --iter.m_leaf_pos; 00354 } 00355 } 00356 00357 template<typename K, typename V> 00358 const V& fairport::btree_node_nonleaf<K,V>::lookup(const K& k) const 00359 { 00360 int location = this->binary_search(k); 00361 00362 if(location == -1) 00363 throw key_not_found<K>(k); 00364 00365 return get_child(location)->lookup(k); 00366 } 00367 00368 template<typename K, typename V> 00369 void fairport::btree_node_nonleaf<K,V>::first(btree_iter_impl<K,V>& iter) const 00370 { 00371 iter.m_path.push_back(std::make_pair(const_cast<btree_node_nonleaf<K,V>*>(this), 0)); 00372 get_child(0)->first(iter); 00373 } 00374 00375 template<typename K, typename V> 00376 void fairport::btree_node_nonleaf<K,V>::last(btree_iter_impl<K,V>& iter) const 00377 { 00378 iter.m_path.push_back(std::make_pair(const_cast<btree_node_nonleaf<K,V>*>(this), this->num_values()-1)); 00379 get_child(this->num_values()-1)->last(iter); 00380 } 00381 00382 template<typename K, typename V> 00383 void fairport::btree_node_nonleaf<K,V>::next(btree_iter_impl<K,V>& iter) const 00384 { 00385 std::pair<btree_node_nonleaf<K,V>*, uint>& me = iter.m_path.back(); 00386 00387 if(++me.second == this->num_values()) 00388 { 00389 // we're done, pop us off the path and call up 00390 if(iter.m_path.size() > 1) 00391 { 00392 iter.m_path.pop_back(); 00393 iter.m_path.back().first->next(iter); 00394 } 00395 } 00396 else 00397 { 00398 // call into the next leaf 00399 get_child(me.second)->first(iter); 00400 } 00401 } 00402 00403 template<typename K, typename V> 00404 void fairport::btree_node_nonleaf<K,V>::prev(btree_iter_impl<K,V>& iter) const 00405 { 00406 std::pair<btree_node_nonleaf<K,V>*, uint>& me = iter.m_path.back(); 00407 00408 if(me.second == 0) 00409 { 00410 // we're done, pop us off the path and call up 00411 if(iter.m_path.size() > 1) 00412 { 00413 iter.m_path.pop_back(); 00414 iter.m_path.back().first->prev(iter); 00415 } 00416 } 00417 else 00418 { 00419 // call into the next child 00420 get_child(--me.second)->last(iter); 00421 } 00422 } 00423 00424 template<typename K, typename V> 00425 fairport::const_btree_node_iter<K,V>::const_btree_node_iter() 00426 { 00427 m_impl.m_leaf_pos = 0; 00428 m_impl.m_leaf = NULL; 00429 } 00430 00431 template<typename K, typename V> 00432 fairport::const_btree_node_iter<K,V>::const_btree_node_iter(const btree_node<K,V>* root, bool last) 00433 { 00434 if(last) 00435 { 00436 root->last(m_impl); 00437 ++m_impl.m_leaf_pos; 00438 } 00439 else 00440 { 00441 root->first(m_impl); 00442 } 00443 } 00444 00445 #ifdef _MSC_VER 00446 #pragma warning(pop) 00447 #endif 00448 00449 #endif