source: trunk/yat/utility/SegmentTree.h @ 4024

Last change on this file since 4024 was 4024, checked in by Peter, 2 years ago

refs #968; SegmentTree::insert taking rvalue

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 10.5 KB
Line 
1#ifndef theplu_yat_utility_segment_tree
2#define theplu_yat_utility_segment_tree
3
4// $Id: SegmentTree.h 4024 2021-01-04 10:53:27Z peter $
5
6/*
7  Copyright (C) 2010, 2011, 2012, 2013, 2021 Peter Johansson
8
9  This file is part of the yat library, http://dev.thep.lu.se/yat
10
11  The yat library is free software; you can redistribute it and/or
12  modify it under the terms of the GNU General Public License as
13  published by the Free Software Foundation; either version 3 of the
14  License, or (at your option) any later version.
15
16  The yat library is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  General Public License for more details.
20
21  You should have received a copy of the GNU General Public License
22  along with yat. If not, see <http://www.gnu.org/licenses/>.
23*/
24
25#include "Segment.h"
26
27#include "yat_assert.h"
28
29#include <algorithm>
30#include <functional>
31#include <utility>
32
33namespace theplu {
34namespace yat {
35namespace utility {
36
37  /**
38     \brief Base Class for SegmentSet and SegmentMap
39
40     - Container: underlying container (set or map)
41     - Compare: functor comparing elements (same as in Segment)
42     - Value2Key: functor translating a \c const_reference to \c
43       key_type (or \c const&)
44   */
45  template<class Container, class Compare, class Value2Key>
46  class SegmentTree
47  {
48  public:
49    /**
50       \brief key type is same as \c Container 's \c key_type.
51
52       Typically Segment<element_type>.
53    */
54    typedef typename Container::key_type key_type;
55
56    /**
57       \brief value type is same as \c Container 's \c value_type.
58
59       Typically a Segment<element_type> or pair<const
60       Segment<element_type>, Data>.
61    */
62    typedef typename Container::value_type value_type;
63
64    /**
65       \brief element type is same as \c key_type 's value_type.
66
67       If the key held is \c Segment<T>, \c value_type is \c T.
68    */
69    typedef typename key_type::value_type element_type;
70
71    ///  \brief key compare
72    typedef typename Container::key_compare key_compare;
73    /// \brief value compare
74    typedef typename Container::value_compare value_compare;
75    /// \brief element compare
76    typedef Compare element_compare;
77
78    /// \brief pointer
79    typedef typename Container::pointer pointer;
80    /// \brief reference
81    typedef typename Container::reference reference;
82    /// \brief const reference
83    typedef typename Container::const_reference const_reference;
84    /// \brief size_type
85    typedef typename Container::size_type size_type;
86    /// \brief difference_type
87    typedef typename Container::difference_type difference_type;
88    /// \brief iterator
89    typedef typename Container::iterator iterator;
90    /// \brief const_iterator
91    typedef typename Container::const_iterator const_iterator;
92
93    /**
94       \brief creates a SegmentTree with no segments
95     */
96    SegmentTree(void) {}
97
98    /**
99       \brief Destructor
100    */
101    virtual ~SegmentTree(void) {}
102
103    /**
104       \return const iterator pointing to beginning of container
105     */
106    const_iterator begin(void) const { return container_.begin(); }
107
108    /**
109       \return iterator pointing to beginning of container
110     */
111    iterator begin(void) { return container_.begin(); }
112
113    /**
114       \brief erases all values
115     */
116    void clear(void) { container_.clear(); }
117
118    /**
119       \return 1 if there is a Segment that overlaps with \a element
120     */
121    size_type count(const element_type& element) const;
122
123    /**
124       \return \c true if size is zero
125    */
126    bool empty(void) const { return container_.empty(); }
127
128    /**
129       \return a const_iterator pointing to the end of container
130     */
131    const_iterator end(void) const { return container_.end(); }
132
133    /**
134       \return end of container
135     */
136    iterator end(void) { return container_.end(); }
137
138    /**
139       \brief erase values in range [first, last)
140
141       \since New in yat 0.8
142     */
143    void erase(iterator first, iterator last) { container_.erase(first, last);}
144
145    /**
146       erase value pointed to by \a pos
147
148       \since New in yat 0.8
149     */
150    void erase(iterator pos) { container_.erase(pos); }
151
152    /**
153       \return iterator pointing to value containing \a element
154
155       If no value contains \a element, end() is returned.
156     */
157    iterator find(const element_type& element);
158
159    /**
160       \return const iterator pointing to value containing \a element
161
162       If no value contains \a element, end() is returned.
163
164       \return an iterator pointing to the Segment that contains \a
165       element. If no Segment contains \a element, end() is returned.
166     */
167    const_iterator find(const element_type& element) const;
168
169    /**
170       \brief insert value
171
172       if \a value does not overlap with container, insert
173       segment; otherwise do nothing.
174
175       \return a pair where pair.first points to the inserted \a value
176       or if \a value was not inserted it points to a value in
177       container that overlaps with \a value; pair.second is true if
178       \a value was inserted.
179     */
180    std::pair<iterator, bool> insert(const value_type& value);
181
182    /**
183       Same as insert(const&) but move \a value rather than copy.
184
185       \since New in yat 0.19
186     */
187    std::pair<iterator, bool> insert(value_type&& value);
188
189    /**
190       \return Comparison functor to compare two keys (Segment)
191     */
192    key_compare key_comp(void) const
193    {
194      return key_compare(compare);
195    }
196
197    /**
198       \brief similar to lower_bound in std::set and std::map
199
200       \return iterator pointing to first value whose key overlaps
201       with \a element or is greater than \a element.
202     */
203    iterator lower_bound(const element_type& element);
204
205    /**
206       \brief similar to lower_bound in std::set and std::map
207
208       \return const iterator pointing to first value whose key
209       overlaps with \a element or is greater than \a element.
210     */
211    const_iterator lower_bound(const element_type& element) const;
212
213    /**
214       \return number of values in container
215     */
216    size_type size(void) const { return container_.size(); }
217
218    /**
219       \return iterator pointing to first segment that is greater than
220       \a segment.
221     */
222    iterator upper_bound(const element_type& element);
223
224    /**
225       \brief similar to upper_bound in std::set and std::map
226
227       \return iterator pointing to first value whose key is greater
228       than \a element.
229     */
230    const_iterator upper_bound(const element_type& element) const;
231
232    /**
233       \return the \c value_compare object used by the class to sort
234       \c values
235     */
236    value_compare value_comp(void) const { return key_comp(); }
237
238  protected:
239    /// underlying container
240    Container container_;
241
242    /**
243       pair.first first (smallest) segment that overlaps with \a
244       segment and pair.second first (smallest) segment that does not
245       overlap with \a segment.
246     */
247    std::pair<iterator, iterator> overlap_range(const key_type& segment)
248    {
249      iterator first = container_.lower_bound(segment);
250      if (first!=begin()) {
251        --first;
252        if (compare(*first, segment))
253          ++first;
254      }
255      iterator last = first;
256      while (last!=end() && !compare(segment, *last))
257        ++last;
258      YAT_ASSERT(last==end() || compare(segment, *last));
259      return std::make_pair(first, last);
260    }
261
262    // using compiler generated copying
263    //SegmentTree(const SegmentTree&);
264    //SegmentTree& operator=(const SegmentTree&);
265  };
266
267  template<class Container, class Compare, class Value2Key>
268  typename SegmentTree<Container, Compare, Value2Key>::size_type
269  SegmentTree<Container,Compare,Value2Key>::count(const element_type& element) const
270  {
271    if (find(element)==end())
272      return 0;
273    return 1;
274  }
275
276
277  template<class Container, class Compare, class Value2Key>
278  typename SegmentTree<Container, Compare, Value2Key>::const_iterator
279  SegmentTree<Container, Compare, Value2Key>::find(const element_type& vt) const
280  {
281    const_iterator iter = lower_bound(vt);
282    element_compare comp;
283    //    if (iter==end() || comp(vt, iter->begin()))
284    if (iter==end() || comp(vt, Value2Key()(*iter).begin()))
285      return end();
286    return iter;
287  }
288
289
290  template<class Container, class Compare, class Value2Key>
291  typename SegmentTree<Container, Compare, Value2Key>::iterator
292  SegmentTree<Container, Compare, Value2Key>::find(const element_type& vt)
293  {
294    iterator iter = lower_bound(vt);
295    element_compare comp;
296    if (iter==end() || comp(vt, Value2Key()(*iter).begin()))
297      return end();
298    return iter;
299  }
300
301
302  template<typename T, class Compare, class Value2Key>
303  std::pair<typename SegmentTree<T, Compare, Value2Key>::iterator, bool>
304  SegmentTree<T, Compare,Value2Key>::insert(const value_type& segment)
305  {
306    return container_.insert(segment);
307  }
308
309
310  template<typename T, class Compare, class Value2Key>
311  std::pair<typename SegmentTree<T, Compare, Value2Key>::iterator, bool>
312  SegmentTree<T, Compare,Value2Key>::insert(value_type&& segment)
313  {
314    return container_.insert(std::move(segment));
315  }
316
317
318  template<typename T, class Compare, class Value2Key>
319  typename SegmentTree<T, Compare, Value2Key>::iterator
320  SegmentTree<T, Compare,Value2Key>::lower_bound(const element_type& element)
321  {
322    key_type segment(element, element);
323    iterator result = container_.lower_bound(segment);
324    // result is larger or overlapping with segment (i.e.! result<segment)
325    YAT_ASSERT(result==end()
326               || !compare(Value2Key()(*result),segment));
327    return result;
328  }
329
330
331  template<typename T, class Compare, class Value2Key>
332  typename SegmentTree<T, Compare, Value2Key>::const_iterator
333  SegmentTree<T, Compare,Value2Key>::lower_bound(const element_type& element) const
334  {
335    key_type segment(element, element);
336    const_iterator result = container_.lower_bound(segment);
337    // result is larger or overlapping with segment (i.e.! result<segment)
338    YAT_ASSERT(result==end()
339               || !compare(Value2Key()(*result),segment));
340    return result;
341  }
342
343
344  template<typename T, class Compare, class Value2Key>
345  typename SegmentTree<T, Compare, Value2Key>::iterator
346  SegmentTree<T, Compare,Value2Key>::upper_bound(const element_type& element)
347  {
348    key_type segment(element, element);
349    iterator result = container_.upper_bound(segment);
350    Compare comp;
351    Value2Key value2key;
352    if (result==end() || comp(element, value2key(*result).begin()))
353      return result;
354    ++result;
355    // result is larger than segment
356    YAT_ASSERT(result==end() || compare(segment, value2key(*result)));
357    return result;
358  }
359
360
361  template<typename T, class Compare, class Value2Key>
362  typename SegmentTree<T, Compare, Value2Key>::const_iterator
363  SegmentTree<T, Compare,Value2Key>::upper_bound(const element_type& element) const
364  {
365    Segment<element_type, Compare> segment(element, element);
366    const_iterator result = container_.upper_bound(segment);
367    Compare comp;
368    Value2Key value2key;
369    if (result==end() || comp(element, value2key(*result).begin()))
370      return result;
371    ++result;
372    // result is larger than segment
373    YAT_ASSERT(result==end() || compare(segment, value2key(*result)));
374    return result;
375  }
376
377}}}
378#endif
Note: See TracBrowser for help on using the repository browser.