mdds
segment_tree.hpp
1 // SPDX-FileCopyrightText: 2010 - 2025 Kohei Yoshida
2 //
3 // SPDX-License-Identifier: MIT
4 
5 #pragma once
6 
7 #include "./node.hpp"
8 #include "./global.hpp"
9 
10 #include <vector>
11 #include <deque>
12 #include <iostream>
13 #include <map>
14 #include <unordered_map>
15 #include <memory>
16 #include <sstream>
17 #include <type_traits>
18 #include <utility>
19 
20 namespace mdds {
21 
41 template<typename KeyT, typename ValueT>
43 {
44 public:
46  using key_type = KeyT;
48  using value_type = ValueT;
49  using size_type = std::size_t;
50 
51 private:
52  struct segment_type
53  {
54  key_type start;
55  key_type end;
56  value_type value;
57 
58  static constexpr bool is_nothrow_less_v = noexcept(std::declval<key_type>() < std::declval<key_type>()) &&
59  noexcept(std::declval<value_type>() < std::declval<value_type>());
60 
61  static constexpr bool is_nothrow_equal_v = noexcept(std::declval<key_type>() == std::declval<key_type>()) &&
62  noexcept(std::declval<value_type>() == std::declval<value_type>());
63 
64  segment_type() = default;
65  segment_type(key_type _start, key_type _end, value_type _value);
66  segment_type(const segment_type&) = default;
67  segment_type(segment_type&&) = default;
68 
69  segment_type& operator=(const segment_type& r) = default;
70  segment_type& operator=(segment_type&& r) = default;
71  bool operator<(const segment_type& r) const noexcept(is_nothrow_less_v && is_nothrow_equal_v);
72  bool operator==(const segment_type& r) const noexcept(is_nothrow_equal_v);
73  bool operator!=(const segment_type& r) const noexcept(is_nothrow_equal_v);
74  };
75 
76  using segment_store_type = std::deque<segment_type>;
77  using value_pos_type = typename segment_store_type::size_type;
78  using value_chain_type = std::vector<value_pos_type>;
79 
80  using node_chain_type = std::vector<st::detail::node_base*>;
81  using value_to_nodes_type = std::map<value_pos_type, node_chain_type>;
82 
83  struct nonleaf_value_type
84  {
85  std::unique_ptr<value_chain_type> data_chain;
86 
87  nonleaf_value_type()
88  {}
89  nonleaf_value_type(const nonleaf_value_type& r)
90  {
91  if (r.data_chain)
92  data_chain = std::make_unique<value_chain_type>(*r.data_chain);
93  }
94 
95  bool operator==(const nonleaf_value_type& r) const
96  {
97  return data_chain == r.data_chain;
98  }
99 
100  ~nonleaf_value_type()
101  {}
102  };
103 
104  struct leaf_value_type
105  {
106  std::unique_ptr<value_chain_type> data_chain;
107 
108  leaf_value_type()
109  {}
110  leaf_value_type(const leaf_value_type& r)
111  {
112  if (r.data_chain)
113  data_chain = std::make_unique<value_chain_type>(*r.data_chain);
114  }
115 
116  bool operator==(const leaf_value_type& r) const
117  {
118  return data_chain == r.data_chain;
119  }
120 
121  ~leaf_value_type()
122  {}
123  };
124 
125 public:
126  using node = st::detail::node<key_type, leaf_value_type>;
127  using node_ptr = typename node::node_ptr;
128  using nonleaf_node = typename st::detail::nonleaf_node<key_type, nonleaf_value_type>;
129 
130 private:
131  class search_result_inserter;
132 
137  class search_results_base
138  {
139  friend class search_result_inserter;
140 
141  public:
142  typedef std::vector<value_chain_type*> res_chains_type;
143  typedef std::shared_ptr<res_chains_type> res_chains_ptr;
144 
145  protected:
146  search_results_base(const segment_store_type& segment_store) : m_segment_store(&segment_store)
147  {}
148 
149  search_results_base(const search_results_base& r)
150  : m_segment_store(r.m_segment_store), mp_res_chains(r.mp_res_chains)
151  {}
152 
153  bool empty() const;
154 
155  size_type size() const;
156 
157  void push_back_chain(value_chain_type* chain);
158 
159  const segment_store_type* get_segment_store() const
160  {
161  return m_segment_store;
162  }
163 
164  const res_chains_ptr& get_res_chains() const
165  {
166  return mp_res_chains;
167  }
168 
169  private:
170  const segment_store_type* m_segment_store = nullptr;
171  res_chains_ptr mp_res_chains;
172  };
173 
174  class const_iterator_base
175  {
176  friend class segment_tree;
177 
178  protected:
179  typedef typename search_results_base::res_chains_type res_chains_type;
180  typedef typename search_results_base::res_chains_ptr res_chains_ptr;
181 
182  const_iterator_base(const segment_store_type* segment_store, const res_chains_ptr& p)
183  : m_segment_store(segment_store), mp_res_chains(p), m_end_pos(true)
184  {}
185 
186  public:
187  using iterator_category = std::bidirectional_iterator_tag;
188  using value_type = const segment_tree::segment_type;
189  using pointer = value_type*;
190  using reference = value_type&;
191  using difference_type = std::ptrdiff_t;
192 
193  const_iterator_base() = default;
194  const_iterator_base(const const_iterator_base& r) = default;
195  const_iterator_base& operator=(const const_iterator_base& r) = default;
196 
197  value_type* operator++();
198  value_type* operator--();
199 
200  bool operator==(const const_iterator_base& r) const;
201  bool operator!=(const const_iterator_base& r) const;
202 
203  value_type& operator*()
204  {
205  return cur_value();
206  }
207 
208  const value_type* operator->()
209  {
210  return &cur_value();
211  }
212 
213  protected:
214  void move_to_front();
215  void move_to_end();
216 
217  private:
218  value_type& cur_value()
219  {
220  auto pos = *m_cur_pos_in_chain;
221  return (*m_segment_store)[pos];
222  }
223 
224  size_type cur_pos() const
225  {
226  return *m_cur_pos_in_chain;
227  }
228 
229  const segment_store_type* m_segment_store = nullptr;
230  res_chains_ptr mp_res_chains;
231  typename res_chains_type::const_iterator m_cur_chain;
232  typename value_chain_type::const_iterator m_cur_pos_in_chain;
233  bool m_end_pos = true;
234  };
235 
236  class search_result_inserter
237  {
238  public:
239  search_result_inserter(search_results_base& results) : m_results(results)
240  {}
241  void operator()(value_chain_type* node_data)
242  {
243  if (!node_data)
244  return;
245 
246  m_results.push_back_chain(node_data);
247  }
248 
249  private:
250  search_results_base& m_results;
251  };
252 
253  static constexpr bool nothrow_default_constructible_v =
254  std::is_nothrow_default_constructible_v<std::vector<nonleaf_node>> &&
255  std::is_nothrow_default_constructible_v<segment_store_type> &&
256  std::is_nothrow_default_constructible_v<value_to_nodes_type> &&
257  std::is_nothrow_default_constructible_v<node_ptr>;
258 
259  static constexpr bool nothrow_move_constructible_v =
260  std::is_nothrow_move_constructible_v<std::vector<nonleaf_node>> &&
261  std::is_nothrow_move_constructible_v<segment_store_type> &&
262  std::is_nothrow_move_constructible_v<value_to_nodes_type> && std::is_nothrow_move_constructible_v<node_ptr>;
263 
264  static constexpr bool nothrow_swappable_v =
265  std::is_nothrow_swappable_v<std::vector<nonleaf_node>> && std::is_nothrow_swappable_v<segment_store_type> &&
266  std::is_nothrow_swappable_v<value_to_nodes_type> && std::is_nothrow_swappable_v<node_ptr>;
267 
268  static constexpr bool nothrow_move_assignable_v = nothrow_move_constructible_v && nothrow_swappable_v;
269 
270 public:
271  class search_results : public search_results_base
272  {
273  friend class segment_tree;
274 
275  typedef typename search_results_base::res_chains_type res_chains_type;
276  typedef typename search_results_base::res_chains_ptr res_chains_ptr;
277 
278  search_results(const segment_store_type& segment_tree) : search_results_base(segment_tree)
279  {}
280 
281  public:
282  class const_iterator : public const_iterator_base
283  {
284  friend class segment_tree<KeyT, ValueT>::search_results;
285 
286  private:
287  const_iterator(const segment_store_type* segment_store, const res_chains_ptr& p)
288  : const_iterator_base(segment_store, p)
289  {}
290 
291  public:
292  const_iterator() : const_iterator_base()
293  {}
294 
295  const_iterator(const const_iterator& r) : const_iterator_base(r)
296  {}
297 
298  const_iterator& operator=(const const_iterator& r)
299  {
300  const_iterator_base::operator=(r);
301  return *this;
302  }
303  };
304 
310  bool empty() const
311  {
312  return search_results_base::empty();
313  }
314 
320  size_type size() const
321  {
322  return search_results_base::size();
323  }
324 
325  typename search_results::const_iterator begin() const
326  {
327  typename search_results::const_iterator it(
328  search_results_base::get_segment_store(), search_results_base::get_res_chains());
329  it.move_to_front();
330  return it;
331  }
332 
333  typename search_results::const_iterator end() const
334  {
335  typename search_results::const_iterator it(
336  search_results_base::get_segment_store(), search_results_base::get_res_chains());
337  it.move_to_end();
338  return it;
339  }
340  };
341 
342  segment_tree() noexcept(nothrow_default_constructible_v);
343  segment_tree(const segment_tree& r);
344  segment_tree(segment_tree&& r) = default;
345  ~segment_tree();
346 
347  segment_tree& operator=(const segment_tree& r);
348  segment_tree& operator=(segment_tree&& r) noexcept(nothrow_move_assignable_v);
349 
357  bool operator==(const segment_tree& r) const;
358 
359  bool operator!=(const segment_tree& r) const;
360 
367  bool valid_tree() const noexcept
368  {
369  return m_valid_tree;
370  }
371 
378  void build_tree();
379 
388  void insert(key_type start_key, key_type end_key, value_type value);
389 
406  search_results search(const key_type& point) const;
407 
415  void erase(const typename search_results::const_iterator& pos);
416 
438  template<typename Pred>
439  size_type erase_if(Pred pred);
440 
446  void swap(segment_tree& r) noexcept(nothrow_swappable_v);
447 
451  void clear();
452 
456  size_type size() const;
457 
461  bool empty() const;
462 
468  size_type leaf_size() const
469  noexcept(noexcept(st::detail::count_leaf_nodes<size_type>(m_left_leaf.get(), m_right_leaf.get())))
470  {
471  return st::detail::count_leaf_nodes<size_type>(m_left_leaf.get(), m_right_leaf.get());
472  }
473 
479  std::string to_string() const;
480 
487  std::vector<key_type> boundary_keys() const;
488 
490  {
491  struct leaf_node
492  {
493  key_type key = {};
494  std::vector<value_type> value_chain;
495  };
496 
497  std::vector<leaf_node> leaf_nodes;
498  };
499 
500  void check_integrity(const integrity_check_properties& props) const;
501 
502 private:
503  static void create_leaf_node_instances(std::vector<key_type> keys, node_ptr& left, node_ptr& right);
504 
510  void descend_tree_and_mark(
511  st::detail::node_base* pnode, value_pos_type value, const key_type& start_key, const key_type& end_key,
512  node_chain_type& nodelist);
513 
514  void build_leaf_nodes();
515 
520  void remove_data_from_nodes(node_chain_type& nodelist, value_pos_type value);
521  void remove_data_from_chain(value_chain_type& chain, value_pos_type value);
522  void remove_value_pos(size_type pos);
523 
524  void clear_all_nodes();
525 
526 private:
527  struct tree_dumper_traits
528  {
529  using leaf_type = node;
530  using nonleaf_type = nonleaf_node;
531  using tree_type = segment_tree;
532 
533  struct to_string
534  {
535  const tree_type& tree;
536 
537  to_string(const tree_type& _tree);
538  std::string operator()(const leaf_type& leaf) const;
539  std::string operator()(const nonleaf_type& nonleaf) const;
540  };
541  };
542 
543  std::vector<nonleaf_node> m_nonleaf_node_pool;
544 
550  segment_store_type m_segment_store;
551 
557  value_to_nodes_type m_tagged_nodes_map;
558 
559  nonleaf_node* m_root_node;
560  node_ptr m_left_leaf;
561  node_ptr m_right_leaf;
562  bool m_valid_tree;
563 };
564 
565 } // namespace mdds
566 
567 #include "segment_tree_def.inl"
size_type leaf_size() const noexcept(noexcept(st::detail::count_leaf_nodes< size_type >(m_left_leaf.get(), m_right_leaf.get())))
Definition: segment_tree.hpp:468
Definition: segment_tree.hpp:42
bool empty() const
Definition: segment_tree.hpp:310
bool valid_tree() const noexcept
Definition: segment_tree.hpp:367
Definition: node.hpp:105
std::vector< key_type > boundary_keys() const
std::string to_string() const
KeyT key_type
Definition: segment_tree.hpp:46
Definition: segment_tree.hpp:271
void erase(const typename search_results::const_iterator &pos)
size_type erase_if(Pred pred)
bool operator==(const segment_tree &r) const
void swap(segment_tree &r) noexcept(nothrow_swappable_v)
size_type size() const
Definition: segment_tree.hpp:320
Definition: cref_wrapper.hpp:12
Definition: node.hpp:24
Definition: segment_tree.hpp:489
ValueT value_type
Definition: segment_tree.hpp:48
size_type size() const
bool empty() const
search_results search(const key_type &point) const
void insert(key_type start_key, key_type end_key, value_type value)