00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #ifndef CGATOOLS_UTIL_RANGE_INTERSECTOR_HPP_
00016 #define CGATOOLS_UTIL_RANGE_INTERSECTOR_HPP_ 1
00017
00019
00020 #include "cgatools/core.hpp"
00021 #include "cgatools/util/Exception.hpp"
00022
00023 #include <functional>
00024 #include <map>
00025 #include <vector>
00026 #include <algorithm>
00027
00028 namespace cgatools { namespace util {
00029
00057 template < typename TRange,
00058 typename TBoundary,
00059 typename TValue,
00060 typename Overlap,
00061 typename GetBoundary,
00062 typename BoundaryLess = std::less<TBoundary> >
00063 class IntervalTree
00064 {
00065 public:
00066 typedef IntervalTree<TRange, TBoundary, TValue,
00067 Overlap, GetBoundary, BoundaryLess> MyType;
00068 typedef std::pair<const TRange, TValue> value_type;
00069 typedef const value_type* QueryResultType;
00070
00072 IntervalTree(const Overlap& overlap = Overlap(),
00073 const GetBoundary& getBoundary = GetBoundary(),
00074 const BoundaryLess& boundaryLess = BoundaryLess())
00075 : overlap_(overlap),
00076 getBoundary_(getBoundary),
00077 boundaryLess_(boundaryLess),
00078 size_(0), root_(0)
00079 {
00080 }
00081
00083 IntervalTree(const MyType& rhs)
00084 : overlap_(rhs.overlap_),
00085 getBoundary_(rhs.getBoundary_),
00086 boundaryLess_(rhs.boundaryLess_),
00087 size_(rhs.size_), root_(copyNodes(rhs.root_))
00088 {
00089 }
00090
00092 const MyType& operator=(const MyType& rhs)
00093 {
00094 MyType t(rhs);
00095 swap(t);
00096 return *this;
00097 }
00098
00099 ~IntervalTree()
00100 {
00101 freeNodes(root_);
00102 }
00103
00105 void put(const TRange& range, const TValue& value)
00106 {
00107 root_ = doInsert(root_, range, value);
00108 }
00109
00112 void intersect(const TRange& range,
00113 std::vector< QueryResultType >& result ) const
00114 {
00115 result.clear();
00116 doSearch(root_, range, result);
00117 }
00118
00120 size_t size() const { return size_; }
00121
00123 void swap(MyType& rhs)
00124 {
00125 std::swap(overlap_, rhs.overlap_);
00126 std::swap(getBoundary_, rhs.getBoundary_);
00127 std::swap(boundaryLess_, rhs.boundaryLess_);
00128 std::swap(size_, rhs.size_);
00129 std::swap(root_, rhs.root_);
00130 }
00131
00133 void clear()
00134 {
00135 freeNodes(root_);
00136 root_ = 0;
00137 size_ = 0;
00138 }
00139
00142 size_t getMaxDepth() const
00143 {
00144 size_t depth, sz = 0;
00145 depth = doGetDepth(root_, sz);
00146 CGA_ASSERT(size_ == sz);
00147 CGA_ASSERT(0 == root_ || depth > 0);
00148 return depth;
00149 }
00150
00151 private:
00152 static const bool RED = true;
00153 static const bool BLACK = false;
00154
00155 struct Node
00156 {
00157 Node(const TRange& k, const TValue& v)
00158 : data_(k, v), color_(RED), left_(0), right_(0)
00159 {
00160 }
00161
00162 const TRange& key() const { return data_.first; }
00163
00164 value_type data_;
00165 TBoundary rmax_;
00166 bool color_;
00167 Node* left_;
00168 Node* right_;
00169 };
00170
00171 private:
00172 Overlap overlap_;
00173 GetBoundary getBoundary_;
00174 BoundaryLess boundaryLess_;
00175 size_t size_;
00176 Node* root_;
00177
00178 private:
00179
00180 bool isRed(const Node* h) const
00181 {
00182 if (0 == h)
00183 return false;
00184 else
00185 return h->color_ == RED;
00186 }
00187
00188 bool less(const TRange& a, const TRange& b)
00189 {
00190 return boundaryLess_( getBoundary_(a, 0), getBoundary_(b, 0) );
00191 }
00192
00193 Node* setRangeMax(Node *h)
00194 {
00195 h->rmax_ = getBoundary_(h->key(), 1);
00196 if (h->left_ && boundaryLess_(h->rmax_, h->left_->rmax_))
00197 h->rmax_ = h->left_->rmax_;
00198 if (h->right_ && boundaryLess_(h->rmax_, h->right_->rmax_))
00199 h->rmax_ = h->right_->rmax_;
00200 return h;
00201 }
00202
00203 void colorFlip(Node* h)
00204 {
00205 h->color_ = !h->color_;
00206 h->left_->color_ = !h->left_->color_;
00207 h->right_->color_ = !h->right_->color_;
00208 }
00209
00210 Node* rotateRight(Node* h)
00211 {
00212 Node* x = h->left_;
00213 h->left_ = x->right_;
00214 x->right_ = setRangeMax(h);
00215 x->color_ = x->right_->color_;
00216 x->right_->color_ = RED;
00217 return setRangeMax(x);
00218 }
00219
00220 Node* rotateLeft(Node* h)
00221 {
00222 Node* x = h->right_;
00223 h->right_ = x->left_;
00224 x->left_ = setRangeMax(h);
00225 x->color_ = x->left_->color_;
00226 x->left_->color_ = RED;
00227 return setRangeMax(x);
00228 }
00229
00230 Node* doInsert(Node* h, const TRange& k, const TValue& v)
00231 {
00232 if (!h)
00233 {
00234 ++size_;
00235 return setRangeMax(new Node(k, v));
00236 }
00237
00238 if (less(k, h->key()))
00239 h->left_ = doInsert(h->left_, k, v);
00240 else
00241 h->right_ = doInsert(h->right_, k, v);
00242
00243 if (isRed(h->right_))
00244 h = rotateLeft(h);
00245
00246 if (isRed(h->left_) && isRed(h->left_->left_))
00247 h = rotateRight(h);
00248
00249 if (isRed(h->left_) && isRed(h->right_))
00250 colorFlip(h);
00251
00252 return setRangeMax(h);
00253 }
00254
00255 void doSearch(const Node* h, const TRange& k,
00256 std::vector< QueryResultType >& result) const
00257 {
00258 if (!h)
00259 return;
00260
00261 if (h->left_ && !boundaryLess_( h->left_->rmax_, getBoundary_(k, 0) ))
00262 doSearch(h->left_, k, result);
00263
00264 if ( boundaryLess_( getBoundary_(k, 1), getBoundary_(h->key(), 0)) )
00265 return;
00266
00267 if (overlap_(h->key(), k))
00268 result.push_back(&h->data_);
00269
00270 if (h->right_ && !boundaryLess_(h->right_->rmax_, getBoundary_(k, 0)) )
00271 doSearch(h->right_, k, result);
00272 }
00273
00274 size_t doGetDepth(const Node* h, size_t& sz) const
00275 {
00276 if (!h)
00277 return 0;
00278
00279 sz += 1;
00280
00281
00282 CGA_ASSERT(!h->right_ || h->left_);
00283
00284 CGA_ASSERT(!boundaryLess_(h->rmax_, getBoundary_(h->key(), 1)));
00285 if (h->left_)
00286 CGA_ASSERT(!boundaryLess_(h->rmax_, h->left_->rmax_));
00287 if (h->right_)
00288 CGA_ASSERT(!boundaryLess_(h->rmax_, h->right_->rmax_));
00289
00290 CGA_ASSERT(!isRed(h->right_));
00291 CGA_ASSERT(!(isRed(h->left_) && isRed(h->left_->left_)));
00292
00293
00294 return 1 + std::max(doGetDepth(h->left_, sz), doGetDepth(h->right_, sz));
00295 }
00296
00297 void freeNodes(Node *h)
00298 {
00299 if (!h)
00300 return;
00301 freeNodes(h->left_);
00302 freeNodes(h->right_);
00303 delete h;
00304 }
00305
00306 Node* copyNodes(Node *h)
00307 {
00308 if (!h)
00309 return 0;
00310 Node* t = new Node(*h);
00311 t->left_ = t->right_ = 0;
00312 try
00313 {
00314 t->left_ = copyNodes(h->left_);
00315 t->right_ = copyNodes(h->right_);
00316 }
00317 catch (const std::exception& )
00318 {
00319 freeNodes(t);
00320 throw;
00321 }
00322 return t;
00323 }
00324 };
00325
00326 } }
00327
00328 #endif // CGATOOLS_UTIL_RANGE_INTERSECTOR_HPP_