#ifndef __INTERVAL_TREE_H #define __INTERVAL_TREE_H #include #include #include namespace interval_tree { template class Interval { public: K start; K stop; T value; Interval(K s, K e, const T& v) : start(s) , stop(e) , value(v) { } }; template int intervalStart(const Interval& i) { return i.start; } template int intervalStop(const Interval& i) { return i.stop; } template std::ostream& operator<<(std::ostream& out, Interval& i) { out << "Interval(" << i.start << ", " << i.stop << "): " << i.value; return out; } template class IntervalStartSorter { public: bool operator() (const Interval& a, const Interval& b) { return a.start < b.start; } }; template class IntervalTree { public: typedef Interval interval; typedef std::vector intervalVector; typedef IntervalTree intervalTree; intervalVector intervals; intervalTree* left; intervalTree* right; int center; IntervalTree(void) : left(NULL) , right(NULL) , center(0) { } IntervalTree(const intervalTree& other) { center = other.center; intervals = other.intervals; if (other.left) { left = (intervalTree*) malloc(sizeof(intervalTree)); *left = *other.left; } else { left = NULL; } if (other.right) { right = new intervalTree(); *right = *other.right; } else { right = NULL; } } IntervalTree& operator=(const intervalTree& other) { center = other.center; intervals = other.intervals; if (other.left) { left = new intervalTree(); *left = *other.left; } else { left = NULL; } if (other.right) { right = new intervalTree(); *right = *other.right; } else { right = NULL; } return *this; } IntervalTree( intervalVector& ivals, unsigned int depth = 16, unsigned int minbucket = 64, int leftextent = 0, int rightextent = 0, unsigned int maxbucket = 512 ) : left(NULL) , right(NULL) { --depth; IntervalStartSorter intervalStartSorter; if (depth == 0 || (ivals.size() < minbucket && ivals.size() < maxbucket)) { sort(ivals.begin(), ivals.end(), intervalStartSorter); intervals = ivals; } else { if (leftextent == 0 && rightextent == 0) { // sort intervals by start sort(ivals.begin(), ivals.end(), intervalStartSorter); } int leftp = 0; int rightp = 0; int centerp = 0; if (leftextent || rightextent) { leftp = leftextent; rightp = rightextent; } else { leftp = ivals.front().start; std::vector stops; stops.resize(ivals.size()); transform(ivals.begin(), ivals.end(), stops.begin(), intervalStop); rightp = *max_element(stops.begin(), stops.end()); } //centerp = ( leftp + rightp ) / 2; centerp = ivals.at(ivals.size() / 2).start; center = centerp; intervalVector lefts; intervalVector rights; for (typename intervalVector::iterator i = ivals.begin(); i != ivals.end(); ++i) { interval& interval = *i; if (interval.stop < center) { lefts.push_back(interval); } else if (interval.start > center) { rights.push_back(interval); } else { intervals.push_back(interval); } } if (!lefts.empty()) { left = new intervalTree(lefts, depth, minbucket, leftp, centerp); } if (!rights.empty()) { right = new intervalTree(rights, depth, minbucket, centerp, rightp); } } } void findOverlapping(K start, K stop, intervalVector& overlapping) { if (!intervals.empty() && ! (stop < intervals.front().start)) { for (typename intervalVector::iterator i = intervals.begin(); i != intervals.end(); ++i) { interval& interval = *i; if (interval.stop >= start && interval.start <= stop) { overlapping.push_back(interval); } } } if (left && start <= center) { left->findOverlapping(start, stop, overlapping); } if (right && stop >= center) { right->findOverlapping(start, stop, overlapping); } } void findContained(K start, K stop, intervalVector& contained) { if (!intervals.empty() && ! (stop < intervals.front().start)) { for (typename intervalVector::iterator i = intervals.begin(); i != intervals.end(); ++i) { interval& interval = *i; if (interval.start >= start && interval.stop <= stop) { contained.push_back(interval); } } } if (left && start <= center) { left->findContained(start, stop, contained); } if (right && stop >= center) { right->findContained(start, stop, contained); } } ~IntervalTree(void) { // traverse the left and right // delete them all the way down if (left) { delete left; } if (right) { delete right; } } }; } #endif