#ifndef theplu_yat_utility_segment_tree #define theplu_yat_utility_segment_tree // $Id: SegmentTree.h 2788 2012-07-25 22:51:16Z peter $ /* Copyright (C) 2010, 2011, 2012 Peter Johansson This file is part of the yat library, http://dev.thep.lu.se/yat The yat library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. The yat library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with yat. If not, see . */ #include "Segment.h" #include "yat_assert.h" #include #include namespace theplu { namespace yat { namespace utility { /** \brief Base Class for SegmentSet and SegmentMap - Container: underlying container (set or map) - Compare: functor comparing elements (same as in Segment) - Value2Key: functor translating a \c const_reference to \c key_type (or \c const&) */ template class SegmentTree { public: /** \brief key type is same as \c Container 's \c key_type. Typically Segment. */ typedef typename Container::key_type key_type; /** \brief value type is same as \c Container 's \c value_type. Typically a Segment or pair, Data>. */ typedef typename Container::value_type value_type; /** \brief element type is same as \c key_type 's value_type. If the key held is \c Segment, \c value_type is \c T. */ typedef typename key_type::value_type element_type; /// \brief key compare typedef typename Container::key_compare key_compare; /// \brief value compare typedef typename Container::value_compare value_compare; /// \brief element compare typedef Compare element_compare; /// \brief pointer typedef typename Container::pointer pointer; /// \brief reference typedef typename Container::reference reference; /// \brief const reference typedef typename Container::const_reference const_reference; /// \brief size_type typedef typename Container::size_type size_type; /// \brief difference_type typedef typename Container::difference_type difference_type; /// \brief iterator typedef typename Container::iterator iterator; /// \brief const_iterator typedef typename Container::const_iterator const_iterator; /** \brief creates a SegmentTree with no segments */ SegmentTree(void) {} /** \brief Destructor */ virtual ~SegmentTree(void) {} /** \return const iterator pointing to beginning of container */ const_iterator begin(void) const { return container_.begin(); } /** \return iterator pointing to beginning of container */ iterator begin(void) { return container_.begin(); } /** \brief erases all values */ void clear(void) { container_.clear(); } /** \return 1 if there is a Segment that overlaps with \a element */ size_type count(const element_type& element) const; /** \return \c true if size is zero */ bool empty(void) const { return container_.empty(); } /** \return a const_iterator pointing to the end of container */ const_iterator end(void) const { return container_.end(); } /** \return end of container */ iterator end(void) { return container_.end(); } /** \brief erase values in range [first, last) \since New in yat 0.8 */ void erase(iterator first, iterator last) { container_.erase(first, last);} /** erase value pointed to by \a pos \since New in yat 0.8 */ void erase(iterator pos) { container_.erase(pos); } /** \return iterator pointing to value containing \a element If no value contains \a element, end() is returned. */ iterator find(const element_type& element); /** \return const iterator pointing to value containing \a element If no value contains \a element, end() is returned. \return an iterator pointing to the Segment that contains \a vt. If no Segment contains \a vt, end() is returned. */ const_iterator find(const element_type& vt) const; /** \brief insert value if \a value does not overlap with container, insert segment; otherwise do nothing. \return a pair where pair.first points to the inserted \a value or if \a value was not inserted it points to a value in container that overlaps with \a value; pair.second is true if \a value was inserted. */ std::pair insert(const value_type& value); /** \return Comparison functor to compare two keys (Segment) */ key_compare key_comp(void) const { return key_compare(compare); } /** \brief similar to lower_bound in std::set and std::map \return iterator pointing to first value whose key overlaps with \a element or is greater than \a element. */ iterator lower_bound(const element_type& element); /** \brief similar to lower_bound in std::set and std::map \return const iterator pointing to first value whose key overlaps with \a element or is greater than \a element. */ const_iterator lower_bound(const element_type& element) const; /** \return number of values in container */ size_type size(void) const { return container_.size(); } /** \return iterator pointing to first segment that is greater than \a segment. */ iterator upper_bound(const element_type& element); /** \brief similar to upper_bound in std::set and std::map \return iterator pointing to first value whose key is greater than \a element. */ const_iterator upper_bound(const element_type& element) const; /** \return the \c value_compare object used by the class to sort \c values */ value_compare value_comp(void) const { return key_comp(); } protected: /// underlying container Container container_; /** pair.first first (smallest) segment that overlaps with \a segment and pair.second first (smallest) segment that does not overlap with \a segment. */ std::pair overlap_range(const key_type& segment) { iterator first = container_.lower_bound(segment); if (first!=begin()) { --first; if (compare(*first, segment)) ++first; } iterator last = first; while (last!=end() && !compare(segment, *last)) ++last; YAT_ASSERT(last==end() || compare(segment, *last)); return std::make_pair(first, last); } // using compiler generated copying //SegmentTree(const SegmentTree&); //SegmentTree& operator=(const SegmentTree&); }; template typename SegmentTree::size_type SegmentTree::count(const element_type& element) const { if (find(element)==end()) return 0; return 1; } template typename SegmentTree::const_iterator SegmentTree::find(const element_type& vt) const { const_iterator iter = lower_bound(vt); element_compare comp; // if (iter==end() || comp(vt, iter->begin())) if (iter==end() || comp(vt, Value2Key()(*iter).begin())) return end(); return iter; } template typename SegmentTree::iterator SegmentTree::find(const element_type& vt) { iterator iter = lower_bound(vt); element_compare comp; if (iter==end() || comp(vt, Value2Key()(*iter).begin())) return end(); return iter; } template std::pair::iterator, bool> SegmentTree::insert(const value_type& segment) { return container_.insert(segment); } template typename SegmentTree::iterator SegmentTree::lower_bound(const element_type& element) { key_type segment(element, element); iterator result = container_.lower_bound(segment); // result is larger or overlapping with segment (i.e.! result typename SegmentTree::const_iterator SegmentTree::lower_bound(const element_type& element) const { key_type segment(element, element); const_iterator result = container_.lower_bound(segment); // result is larger or overlapping with segment (i.e.! result typename SegmentTree::iterator SegmentTree::upper_bound(const element_type& element) { key_type segment(element, element); iterator result = container_.upper_bound(segment); Compare comp; Value2Key value2key; if (result==end() || comp(element, value2key(*result).begin())) return result; ++result; // result is larger than segment YAT_ASSERT(result==end() || compare(segment, value2key(*result))); return result; } template typename SegmentTree::const_iterator SegmentTree::upper_bound(const element_type& element) const { Segment segment(element, element); const_iterator result = container_.upper_bound(segment); Compare comp; Value2Key value2key; if (result==end() || comp(element, value2key(*result).begin())) return result; ++result; // result is larger than segment YAT_ASSERT(result==end() || compare(segment, value2key(*result))); return result; } }}} #endif