mdds
Loading...
Searching...
No Matches
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
20namespace mdds {
21
41template<typename KeyT, typename ValueT>
42class segment_tree
43{
44public:
46 using key_type = KeyT;
48 using value_type = ValueT;
49 using size_type = std::size_t;
50
51private:
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
125public:
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
130private:
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
270public:
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 {
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
379
388 void insert(key_type start_key, key_type end_key, value_type value);
389
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 {
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
502private:
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
526private:
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"
Definition segment_tree.hpp:272
size_type size() const
Definition segment_tree.hpp:320
bool empty() const
Definition segment_tree.hpp:310
bool empty() const
KeyT key_type
Definition segment_tree.hpp:46
ValueT value_type
Definition segment_tree.hpp:48
void insert(key_type start_key, key_type end_key, value_type value)
void erase(const typename search_results::const_iterator &pos)
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
size_type size() const
bool operator==(const segment_tree &r) const
std::vector< key_type > boundary_keys() const
std::string to_string() const
search_results search(const key_type &point) const
void swap(segment_tree &r) noexcept(nothrow_swappable_v)
bool valid_tree() const noexcept
Definition segment_tree.hpp:367
size_type erase_if(Pred pred)
Definition segment_tree.hpp:490
Definition node.hpp:25