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

Last change on this file since 2361 was 2361, checked in by Peter, 13 years ago

base class should always have virtual destructor (or non-virtual protected) refs#640.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 8.5 KB
Line 
1#ifndef theplu_yat_utility_segment_tree
2#define theplu_yat_utility_segment_tree
3
4// $Id: SegmentTree.h 2361 2010-12-04 05:02:10Z peter $
5
6/*
7  Copyright (C) 2010 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
32namespace theplu {
33namespace yat {
34namespace utility {
35
36  /**
37     \brief Base Class for SegmentSet and SegmentMap
38
39     - Container: underlying container (set or map)
40     - Compare: functor comparing elements (same as in Segment)
41     - Value2Key: functor translating a \c const_reference to \c
42       key_type (or \c const&)
43   */
44  template<class Container, class Compare, class Value2Key>
45  class SegmentTree
46  {
47  public:
48    /// \brief key type
49    typedef typename Container::key_type key_type;
50    /// \brief value type
51    typedef typename Container::value_type value_type;
52    /// \brief element type
53    typedef typename key_type::value_type element_type;
54
55    /// \brief key compare
56    typedef typename Container::key_compare key_compare;
57    /// \brief calue compare
58    typedef typename Container::value_compare value_compare;
59    /// \brief element compare
60    typedef Compare element_compare;
61
62    /// \brief pointer
63    typedef typename Container::pointer pointer;
64    /// \brief reference
65    typedef typename Container::reference reference;
66    /// \brief const reference
67    typedef typename Container::const_reference const_reference;
68    /// \brief size_type
69    typedef typename Container::size_type size_type;
70    /// \brief difference_type
71    typedef typename Container::difference_type difference_type;
72    /// \brief iterator
73    typedef typename Container::iterator iterator;
74    /// \brief const_iterator
75    typedef typename Container::const_iterator const_iterator;
76
77    /**
78       \brief creates a container with no segments
79     */
80    SegmentTree(void) {}
81
82    /**
83       \brief Destructor
84    */
85    virtual ~SegmentTree(void) {}
86
87    /**
88       \return const iterator to first Segment
89     */
90    const_iterator begin(void) const { return container_.begin(); }
91
92    /**
93       \return iterator to first Segment
94     */
95    iterator begin(void) { return container_.begin(); }
96
97    /**
98       \brief erases all segments
99     */
100    void clear(void) { container_.clear(); }
101
102    /**
103       \return 1 if there is a set that overlaps with \a element
104     */
105    size_type count(const element_type& element) const;
106
107    /**
108       \return \c true
109    */
110    bool empty(void) const { return container_.empty(); }
111
112    /**
113       \return end of set
114     */
115    const_iterator end(void) const { return container_.end(); }
116
117    /**
118       \return end of set
119     */
120    iterator end(void) { return container_.end(); }
121
122    /**
123       \return an iterator pointing to the Segment that contains \a
124       vt. If no Segment contains \a vt, end() is returned.
125     */
126    const_iterator find(const element_type& vt) const;
127
128    /**
129       \brief insert set
130
131       if \a segment does not overlap with any segment in set, insert
132       segment; otherwise do nothing.
133
134       \return a pair where pair.first points to the added \a segment
135       or if \a segment was not added it points to a Segment in set
136       that overlaps with \a segment; pair.second is true if \a
137       segment was added.
138     */
139    std::pair<iterator, bool> insert(const value_type& segment);
140
141    /**
142       insert \a segment into set. If there is no gap between \a
143       segment and neighboring segments the segments are merged.
144     */
145    const_iterator insert_merge(const value_type& segment);
146
147    /**
148       \return Comparison functor to compare to segments
149     */
150    key_compare key_comp(void) const 
151    { 
152      return key_compare(compare);
153    }
154
155    /**
156       \return iterator pointing to first segment that overlaps with
157       \a element or is greater than \a element.
158     */
159    iterator lower_bound(const element_type& element);
160
161    /**
162       \return iterator pointing to first segment that overlaps with
163       \a element or is greater than \a element.
164     */
165    const_iterator lower_bound(const element_type& element) const;
166
167    /**
168       \return number of segments in set
169     */
170    size_type size(void) const { return container_.size(); }
171
172    /**
173       \return iterator pointing to first segment that is greater than
174       \a segment.
175     */
176    iterator upper_bound(const element_type& element);
177
178    /**
179       \return iterator pointing to first segment that is greater than
180       \a segment.
181     */
182    const_iterator upper_bound(const element_type& element) const;
183
184    /**
185       \return Comparison functor to compare to segments
186     */
187    value_compare value_comp(void) const { return key_comp(); }
188
189  protected:
190    /// underlying container
191    Container container_;
192
193    /**
194       pair.first first (smallest) segment that overlaps with \a
195       segment and pair.second first (smallest) segment that does not
196       overlap with \a segment.
197     */
198    std::pair<iterator, iterator> overlap_range(const key_type& segment) 
199    {
200      iterator first = container_.lower_bound(segment);
201      if (first!=begin()) {
202        --first;
203        if (compare(*first, segment))
204          ++first;
205      }
206      iterator last = first;
207      while (last!=end() && !compare(segment, *last))
208        ++last;
209      YAT_ASSERT(last==end() || compare(segment, *last));
210      return std::make_pair(first, last);
211    }
212
213    // using compiler generated copying
214    //SegmentTree(const SegmentTree&);
215    //SegmentTree& operator=(const SegmentTree&);
216  };
217
218  template<class Container, class Compare, class Value2Key>
219  typename SegmentTree<Container, Compare, Value2Key>::size_type
220  SegmentTree<Container,Compare,Value2Key>::count(const element_type& element) const
221  {
222    if (find(element)==end())
223      return 0;
224    return 1;
225  }
226
227
228  template<class Container, class Compare, class Value2Key>
229  typename SegmentTree<Container, Compare, Value2Key>::const_iterator
230  SegmentTree<Container, Compare, Value2Key>::find(const element_type& vt) const
231  {
232    const_iterator iter = lower_bound(vt);
233    element_compare comp;
234    //    if (iter==end() || comp(vt, iter->begin()))
235    if (iter==end() || comp(vt, Value2Key()(*iter).begin()))
236      return end();
237    return iter;
238  }
239
240
241  template<typename T, class Compare, class Value2Key>
242  std::pair<typename SegmentTree<T, Compare, Value2Key>::iterator, bool> 
243  SegmentTree<T, Compare,Value2Key>::insert(const value_type& segment)
244  {
245    return container_.insert(segment);
246  }
247
248
249  template<typename T, class Compare, class Value2Key>
250  typename SegmentTree<T, Compare, Value2Key>::iterator
251  SegmentTree<T, Compare,Value2Key>::lower_bound(const element_type& element)
252  {
253    key_type segment(element, element);
254    iterator result = container_.lower_bound(segment);
255    // result is larger or overlapping with segment (i.e.! result<segment)
256    YAT_ASSERT(result==end() 
257               || !compare(Value2Key()(*result),segment));
258    return result;
259  }
260
261
262  template<typename T, class Compare, class Value2Key>
263  typename SegmentTree<T, Compare, Value2Key>::const_iterator
264  SegmentTree<T, Compare,Value2Key>::lower_bound(const element_type& element) const
265  {
266    key_type segment(element, element);
267    const_iterator result = container_.lower_bound(segment);
268    // result is larger or overlapping with segment (i.e.! result<segment)
269    YAT_ASSERT(result==end() 
270               || !compare(Value2Key()(*result),segment));
271    return result;
272  }
273
274
275  template<typename T, class Compare, class Value2Key>
276  typename SegmentTree<T, Compare, Value2Key>::iterator
277  SegmentTree<T, Compare,Value2Key>::upper_bound(const element_type& element)
278  {
279    key_type segment(element, element);
280    iterator result = container_.upper_bound(segment);
281    Compare comp;
282    if (result==end() || comp(element, result->begin()))
283      return result;
284    ++result;
285    // result is larger than segment
286    YAT_ASSERT(result==end() || compare(segment, *result));
287    return result;
288  }
289
290
291  template<typename T, class Compare, class Value2Key>
292  typename SegmentTree<T, Compare, Value2Key>::const_iterator
293  SegmentTree<T, Compare,Value2Key>::upper_bound(const element_type& element) const
294  {
295    Segment<T, Compare> segment(element, element);
296    const_iterator result = container_.upper_bound(segment);
297    Compare comp;
298    if (result==end() || comp(element, result->begin()))
299      return result;
300    ++result;
301    // result is larger than segment
302    YAT_ASSERT(result==end() || compare(segment, *result));
303    return result;
304  }
305
306}}}
307#endif
Note: See TracBrowser for help on using the repository browser.