[med-svn] [libvcflib] 01/01: Add plain IntervalTree.h

Andreas Tille tille at debian.org
Fri Jun 24 09:13:15 UTC 2016


This is an automated email from the git hooks/post-receive script.

tille pushed a commit to branch master
in repository libvcflib.

commit 9e7e6030658d2d01ba3990d1a6a213e2c11da0f7
Author: Andreas Tille <tille at debian.org>
Date:   Fri Jun 24 11:12:59 2016 +0200

    Add plain IntervalTree.h
---
 debian/include/IntervalTree.h | 211 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 211 insertions(+)

diff --git a/debian/include/IntervalTree.h b/debian/include/IntervalTree.h
new file mode 100644
index 0000000..6197a8a
--- /dev/null
+++ b/debian/include/IntervalTree.h
@@ -0,0 +1,211 @@
+#ifndef __INTERVAL_TREE_H
+#define __INTERVAL_TREE_H
+
+#include <vector>
+#include <algorithm>
+#include <iostream>
+#include <memory>
+
+template <class T, typename K = std::size_t>
+class Interval {
+public:
+    K start;
+    K stop;
+    T value;
+    Interval(K s, K e, const T& v)
+        : start(s)
+        , stop(e)
+        , value(v)
+    { }
+};
+
+template <class T, typename K>
+K intervalStart(const Interval<T,K>& i) {
+    return i.start;
+}
+
+template <class T, typename K>
+K intervalStop(const Interval<T,K>& i) {
+    return i.stop;
+}
+
+template <class T, typename K>
+  std::ostream& operator<<(std::ostream& out, Interval<T,K>& i) {
+    out << "Interval(" << i.start << ", " << i.stop << "): " << i.value;
+    return out;
+}
+
+template <class T, typename K = std::size_t>
+class IntervalStartSorter {
+public:
+    bool operator() (const Interval<T,K>& a, const Interval<T,K>& b) {
+        return a.start < b.start;
+    }
+};
+
+template <class T, typename K = std::size_t>
+class IntervalTree {
+
+public:
+    typedef Interval<T,K> interval;
+    typedef std::vector<interval> intervalVector;
+    typedef IntervalTree<T,K> intervalTree;
+
+    intervalVector intervals;
+    std::unique_ptr<intervalTree> left;
+    std::unique_ptr<intervalTree> right;
+    K center;
+
+    IntervalTree<T,K>(void)
+        : left(nullptr)
+        , right(nullptr)
+        , center(0)
+    { }
+
+private:
+    std::unique_ptr<intervalTree> copyTree(const intervalTree& orig){
+        return std::unique_ptr<intervalTree>(new intervalTree(orig));
+    }
+public:
+
+    IntervalTree<T,K>(const intervalTree& other)
+    :   intervals(other.intervals),
+        left(other.left ? copyTree(*other.left) : nullptr),
+        right(other.right ? copyTree(*other.right) : nullptr),
+        center(other.center)
+    {
+    }
+
+public:
+
+    IntervalTree<T,K>& operator=(const intervalTree& other) {
+        center = other.center;
+        intervals = other.intervals;
+        left = other.left ? copyTree(*other.left) : nullptr;
+        right = other.right ? copyTree(*other.right) : nullptr;
+        return *this;
+    }
+
+    // Note: changes the order of ivals
+    IntervalTree<T,K>(
+            intervalVector& ivals,
+            std::size_t depth = 16,
+            std::size_t minbucket = 64,
+            K leftextent = 0,
+            K rightextent = 0,
+            std::size_t maxbucket = 512
+            )
+        : left(nullptr)
+        , right(nullptr)
+    {
+
+        --depth;
+        IntervalStartSorter<T,K> intervalStartSorter;
+        if (depth == 0 || (ivals.size() < minbucket && ivals.size() < maxbucket)) {
+            std::sort(ivals.begin(), ivals.end(), intervalStartSorter);
+            intervals = ivals;
+        } else {
+            if (leftextent == 0 && rightextent == 0) {
+                // sort intervals by start
+              std::sort(ivals.begin(), ivals.end(), intervalStartSorter);
+            }
+
+            K leftp = 0;
+            K rightp = 0;
+            K centerp = 0;
+
+            if (leftextent || rightextent) {
+                leftp = leftextent;
+                rightp = rightextent;
+            } else {
+                leftp = ivals.front().start;
+                std::vector<K> stops;
+                stops.resize(ivals.size());
+                transform(ivals.begin(), ivals.end(), stops.begin(), intervalStop<T,K>);
+                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::const_iterator i = ivals.begin(); i != ivals.end(); ++i) {
+                const 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 = std::unique_ptr<intervalTree>(new intervalTree(lefts, depth, minbucket, leftp, centerp));
+            }
+            if (!rights.empty()) {
+                right = std::unique_ptr<intervalTree>(new intervalTree(rights, depth, minbucket, centerp, rightp));
+            }
+        }
+    }
+
+    intervalVector findOverlapping(K start, K stop) const {
+	intervalVector ov;
+	this->findOverlapping(start, stop, ov);
+	return ov;
+    }
+
+    void findOverlapping(K start, K stop, intervalVector& overlapping) const {
+        if (!intervals.empty() && ! (stop < intervals.front().start)) {
+            for (typename intervalVector::const_iterator i = intervals.begin(); i != intervals.end(); ++i) {
+                const 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);
+        }
+
+    }
+
+    intervalVector findContained(K start, K stop) const {
+	intervalVector contained;
+	this->findContained(start, stop, contained);
+	return contained;
+    }
+
+    void findContained(K start, K stop, intervalVector& contained) const {
+        if (!intervals.empty() && ! (stop < intervals.front().start)) {
+            for (typename intervalVector::const_iterator i = intervals.begin(); i != intervals.end(); ++i) {
+                const 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) = default;
+
+};
+
+#endif

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/libvcflib.git



More information about the debian-med-commit mailing list