#pragma once #include "Tree.hpp" namespace tp { template class IntervalKey { public: IntervalKey() = default; IntervalKey(tType start, tType end) { mStart = start; mEnd = end; } inline bool descentRight(const IntervalKey& in) const { if (in.mStart != mStart) return in.mStart > mStart; return in.mEnd > mEnd; } inline bool exactNode(const IntervalKey& in) const { return in.mStart == mStart && in.mEnd == mEnd; } template inline const IntervalKey& getFindKey(const tTreeNodeType* node) const { return *this; } inline const IntervalKey& keyInRightSubtree(const IntervalKey& in) const { return in; } inline const IntervalKey& keyInLeftSubtree(const IntervalKey& in) const { return in; } template inline void updateNodeCache(const tTreeNodeType* node) { mMax = 0; if (node->mRight && node->mRight->key.mMax > mMax) mMax = node->mRight->key.mMax; if (node->mLeft && node->mLeft->key.mMax > mMax) mMax = node->mLeft->key.mMax; if (mMax < mEnd) mMax = mEnd; } public: tType mStart = tType(); tType mEnd = tType(); tType mMax = tType(); }; template class IntervalTree : public AvlTree, tData> { typedef typename AvlTree, tData>::Node Node; public: IntervalTree() = default; template ualni forEachIntersection(tType start, tType end, tFunctor functor) const { ualni debug = 0; forEachIntersectionUtil(this->head(), start, end, functor, debug); return debug; } private: template void forEachIntersectionUtil(const Node* node, tType start, tType end, tFunctor functor, ualni& debug) const { if (node->mHeight == -1) return; // sentinel node (null node) debug++; // If 'start' is to the right of the rightmost point of any interval // in this node and all children, there won't be any matches. if (start > node->key.mMax) return; // Search left children forEachIntersectionUtil(node->mLeft, start, end, functor, debug); // Check this node if (start <= node->key.mEnd && end >= node->key.mStart) { functor(node->key.mStart, node->key.mEnd, node->data); } // If end is to the left of the start of this interval, // then it can't be in any child to the right. if (end < node->key.mStart) return; // Otherwise, search right children forEachIntersectionUtil(node->mRight, start, end, functor, debug); } }; }