/src/mdds-3.1.0/include/mdds/node.hpp
Line | Count | Source |
1 | | /************************************************************************* |
2 | | * |
3 | | * Copyright (c) 2008-2014 Kohei Yoshida |
4 | | * |
5 | | * Permission is hereby granted, free of charge, to any person |
6 | | * obtaining a copy of this software and associated documentation |
7 | | * files (the "Software"), to deal in the Software without |
8 | | * restriction, including without limitation the rights to use, |
9 | | * copy, modify, merge, publish, distribute, sublicense, and/or sell |
10 | | * copies of the Software, and to permit persons to whom the |
11 | | * Software is furnished to do so, subject to the following |
12 | | * conditions: |
13 | | * |
14 | | * The above copyright notice and this permission notice shall be |
15 | | * included in all copies or substantial portions of the Software. |
16 | | * |
17 | | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
18 | | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES |
19 | | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
20 | | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT |
21 | | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
22 | | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
23 | | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
24 | | * OTHER DEALINGS IN THE SOFTWARE. |
25 | | * |
26 | | ************************************************************************/ |
27 | | |
28 | | #ifndef __MDDS_NODE_HXX__ |
29 | | #define __MDDS_NODE_HXX__ |
30 | | |
31 | | #include "mdds/global.hpp" |
32 | | |
33 | | #include <iostream> |
34 | | #include <vector> |
35 | | #include <cassert> |
36 | | #include <sstream> |
37 | | |
38 | | #include <boost/intrusive_ptr.hpp> |
39 | | |
40 | | namespace mdds { namespace st { namespace detail { |
41 | | |
42 | | #ifdef MDDS_DEBUG_NODE_BASE |
43 | | |
44 | | inline std::size_t node_instance_count = 0; |
45 | | |
46 | | #endif |
47 | | |
48 | | struct node_base |
49 | | { |
50 | | node_base* parent; /// parent nonleaf_node |
51 | | bool is_leaf; |
52 | | |
53 | 2.33k | node_base(bool _is_leaf) : parent(nullptr), is_leaf(_is_leaf) |
54 | 2.33k | {} |
55 | 538 | node_base(const node_base& r) : parent(nullptr), is_leaf(r.is_leaf) |
56 | 538 | {} |
57 | | }; |
58 | | |
59 | | /** |
60 | | * Represents a non-leaf node in a segment-tree like structure. |
61 | | */ |
62 | | template<typename KeyT, typename ValueT> |
63 | | struct nonleaf_node : public node_base |
64 | | { |
65 | | using key_type = KeyT; |
66 | | using nonleaf_value_type = ValueT; |
67 | | |
68 | | nonleaf_value_type value_nonleaf; |
69 | | |
70 | | key_type low = {}; /// low range value (inclusive) |
71 | | key_type high = {}; /// high range value (non-inclusive) |
72 | | |
73 | | node_base* left = nullptr; /// left child nonleaf_node |
74 | | node_base* right = nullptr; /// right child nonleaf_node |
75 | | |
76 | | public: |
77 | 381 | nonleaf_node() : node_base(false), value_nonleaf() |
78 | 381 | {} |
79 | | |
80 | | /** |
81 | | * When copying nonleaf_node, only the stored values should be copied. |
82 | | * Connections to the parent, left and right nodes must not be copied. |
83 | | */ |
84 | 0 | nonleaf_node(const nonleaf_node& r) : node_base(r), value_nonleaf(r.value_nonleaf), low(r.low), high(r.high) |
85 | 0 | {} |
86 | | |
87 | | /** |
88 | | * Like the copy constructor, only the stored values should be copied. |
89 | | */ |
90 | | nonleaf_node& operator=(const nonleaf_node& r) |
91 | | { |
92 | | if (this == &r) |
93 | | // assignment to self. |
94 | | return *this; |
95 | | |
96 | | value_nonleaf = r.value_nonleaf; |
97 | | return *this; |
98 | | } |
99 | | |
100 | | bool operator==(const nonleaf_node& r) const |
101 | | { |
102 | | return low == r.low && high == r.high && value_nonleaf == r.value_nonleaf; |
103 | | } |
104 | | |
105 | | bool operator!=(const nonleaf_node& r) const |
106 | | { |
107 | | return !operator==(r); |
108 | | } |
109 | | |
110 | | std::string to_string() const |
111 | | { |
112 | | std::ostringstream os; |
113 | | os << "[" << low << "-" << high << ")"; |
114 | | return os.str(); |
115 | | } |
116 | | }; |
117 | | |
118 | | /** |
119 | | * Represents a leaf node in a segment-tree like structure. |
120 | | */ |
121 | | template<typename KeyT, typename ValueT> |
122 | | struct node : node_base |
123 | | { |
124 | | using key_type = KeyT; |
125 | | using leaf_value_type = ValueT; |
126 | | using node_ptr = boost::intrusive_ptr<node>; |
127 | | |
128 | | static size_t get_instance_count() |
129 | | { |
130 | | #ifdef MDDS_DEBUG_NODE_BASE |
131 | | return node_instance_count; |
132 | | #else |
133 | | return 0; |
134 | | #endif |
135 | | } |
136 | | |
137 | | leaf_value_type value_leaf; |
138 | | |
139 | | key_type key = {}; |
140 | | |
141 | | node_ptr prev; /// previous sibling leaf node. |
142 | | node_ptr next; /// next sibling leaf node. |
143 | | |
144 | | std::size_t refcount = 0; |
145 | | |
146 | | public: |
147 | 1.95k | node() : node_base(true) |
148 | 1.95k | { |
149 | | #ifdef MDDS_DEBUG_NODE_BASE |
150 | | ++node_instance_count; |
151 | | #endif |
152 | 1.95k | } mdds::st::detail::node<unsigned int, mdds::flat_segment_tree<unsigned int, float>::leaf_value_type>::node() Line | Count | Source | 147 | 988 | node() : node_base(true) | 148 | 988 | { | 149 | | #ifdef MDDS_DEBUG_NODE_BASE | 150 | | ++node_instance_count; | 151 | | #endif | 152 | 988 | } |
mdds::st::detail::node<unsigned int, mdds::flat_segment_tree<unsigned int, bool>::leaf_value_type>::node() Line | Count | Source | 147 | 424 | node() : node_base(true) | 148 | 424 | { | 149 | | #ifdef MDDS_DEBUG_NODE_BASE | 150 | | ++node_instance_count; | 151 | | #endif | 152 | 424 | } |
mdds::st::detail::node<unsigned int, mdds::flat_segment_tree<unsigned int, std::__1::shared_ptr<libetonyek::IWORKStyle> >::leaf_value_type>::node() Line | Count | Source | 147 | 540 | node() : node_base(true) | 148 | 540 | { | 149 | | #ifdef MDDS_DEBUG_NODE_BASE | 150 | | ++node_instance_count; | 151 | | #endif | 152 | 540 | } |
|
153 | | |
154 | | /** |
155 | | * When copying node, only the stored values should be copied. |
156 | | * Connections to the parent, left and right nodes must not be copied. |
157 | | */ |
158 | 538 | node(const node& r) : node_base(r), key(r.key) |
159 | 538 | { |
160 | | #ifdef MDDS_DEBUG_NODE_BASE |
161 | | ++node_instance_count; |
162 | | #endif |
163 | 538 | value_leaf = r.value_leaf; |
164 | 538 | } |
165 | | |
166 | | /** |
167 | | * Like the copy constructor, only the stored values should be copied. |
168 | | */ |
169 | | node& operator=(const node& r) |
170 | | { |
171 | | if (this == &r) |
172 | | // assignment to self. |
173 | | return *this; |
174 | | |
175 | | value_leaf = r.value_leaf; |
176 | | return *this; |
177 | | } |
178 | | |
179 | | ~node() |
180 | 2.49k | { |
181 | | #ifdef MDDS_DEBUG_NODE_BASE |
182 | | --node_instance_count; |
183 | | #endif |
184 | 2.49k | } mdds::st::detail::node<unsigned int, mdds::flat_segment_tree<unsigned int, bool>::leaf_value_type>::~node() Line | Count | Source | 180 | 424 | { | 181 | | #ifdef MDDS_DEBUG_NODE_BASE | 182 | | --node_instance_count; | 183 | | #endif | 184 | 424 | } |
mdds::st::detail::node<unsigned int, mdds::flat_segment_tree<unsigned int, std::__1::shared_ptr<libetonyek::IWORKStyle> >::leaf_value_type>::~node() Line | Count | Source | 180 | 1.07k | { | 181 | | #ifdef MDDS_DEBUG_NODE_BASE | 182 | | --node_instance_count; | 183 | | #endif | 184 | 1.07k | } |
mdds::st::detail::node<unsigned int, mdds::flat_segment_tree<unsigned int, float>::leaf_value_type>::~node() Line | Count | Source | 180 | 988 | { | 181 | | #ifdef MDDS_DEBUG_NODE_BASE | 182 | | --node_instance_count; | 183 | | #endif | 184 | 988 | } |
|
185 | | |
186 | | bool operator==(const node& r) const |
187 | | { |
188 | | return key == r.key && value_leaf == r.value_leaf; |
189 | | } |
190 | | |
191 | | bool operator!=(const node& r) const |
192 | | { |
193 | | return !operator==(r); |
194 | | } |
195 | | |
196 | | std::string to_string() const |
197 | | { |
198 | | std::ostringstream os; |
199 | | os << "[" << key << "]"; |
200 | | return os.str(); |
201 | | } |
202 | | }; |
203 | | |
204 | | template<typename KeyT, typename ValueT> |
205 | | inline void intrusive_ptr_add_ref(node<KeyT, ValueT>* p) |
206 | 15.3k | { |
207 | 15.3k | ++p->refcount; |
208 | 15.3k | } void mdds::st::detail::intrusive_ptr_add_ref<unsigned int, mdds::flat_segment_tree<unsigned int, std::__1::shared_ptr<libetonyek::IWORKStyle> >::leaf_value_type>(mdds::st::detail::node<unsigned int, mdds::flat_segment_tree<unsigned int, std::__1::shared_ptr<libetonyek::IWORKStyle> >::leaf_value_type>*) Line | Count | Source | 206 | 5.21k | { | 207 | 5.21k | ++p->refcount; | 208 | 5.21k | } |
void mdds::st::detail::intrusive_ptr_add_ref<unsigned int, mdds::flat_segment_tree<unsigned int, float>::leaf_value_type>(mdds::st::detail::node<unsigned int, mdds::flat_segment_tree<unsigned int, float>::leaf_value_type>*) Line | Count | Source | 206 | 6.79k | { | 207 | 6.79k | ++p->refcount; | 208 | 6.79k | } |
void mdds::st::detail::intrusive_ptr_add_ref<unsigned int, mdds::flat_segment_tree<unsigned int, bool>::leaf_value_type>(mdds::st::detail::node<unsigned int, mdds::flat_segment_tree<unsigned int, bool>::leaf_value_type>*) Line | Count | Source | 206 | 3.29k | { | 207 | 3.29k | ++p->refcount; | 208 | 3.29k | } |
|
209 | | |
210 | | template<typename KeyT, typename ValueT> |
211 | | inline void intrusive_ptr_release(node<KeyT, ValueT>* p) |
212 | 15.3k | { |
213 | 15.3k | --p->refcount; |
214 | 15.3k | if (!p->refcount) |
215 | 2.49k | delete p; |
216 | 15.3k | } void mdds::st::detail::intrusive_ptr_release<unsigned int, mdds::flat_segment_tree<unsigned int, bool>::leaf_value_type>(mdds::st::detail::node<unsigned int, mdds::flat_segment_tree<unsigned int, bool>::leaf_value_type>*) Line | Count | Source | 212 | 3.29k | { | 213 | 3.29k | --p->refcount; | 214 | 3.29k | if (!p->refcount) | 215 | 424 | delete p; | 216 | 3.29k | } |
void mdds::st::detail::intrusive_ptr_release<unsigned int, mdds::flat_segment_tree<unsigned int, std::__1::shared_ptr<libetonyek::IWORKStyle> >::leaf_value_type>(mdds::st::detail::node<unsigned int, mdds::flat_segment_tree<unsigned int, std::__1::shared_ptr<libetonyek::IWORKStyle> >::leaf_value_type>*) Line | Count | Source | 212 | 5.21k | { | 213 | 5.21k | --p->refcount; | 214 | 5.21k | if (!p->refcount) | 215 | 1.07k | delete p; | 216 | 5.21k | } |
void mdds::st::detail::intrusive_ptr_release<unsigned int, mdds::flat_segment_tree<unsigned int, float>::leaf_value_type>(mdds::st::detail::node<unsigned int, mdds::flat_segment_tree<unsigned int, float>::leaf_value_type>*) Line | Count | Source | 212 | 6.79k | { | 213 | 6.79k | --p->refcount; | 214 | 6.79k | if (!p->refcount) | 215 | 988 | delete p; | 216 | 6.79k | } |
|
217 | | |
218 | | template<typename NodePtrT> |
219 | | void link_nodes(NodePtrT& left, NodePtrT& right) |
220 | 1.66k | { |
221 | 1.66k | left->next = right; |
222 | 1.66k | right->prev = left; |
223 | 1.66k | } void mdds::st::detail::link_nodes<boost::intrusive_ptr<mdds::st::detail::node<unsigned int, mdds::flat_segment_tree<unsigned int, float>::leaf_value_type> > >(boost::intrusive_ptr<mdds::st::detail::node<unsigned int, mdds::flat_segment_tree<unsigned int, float>::leaf_value_type> >&, boost::intrusive_ptr<mdds::st::detail::node<unsigned int, mdds::flat_segment_tree<unsigned int, float>::leaf_value_type> >&) Line | Count | Source | 220 | 1.12k | { | 221 | 1.12k | left->next = right; | 222 | 1.12k | right->prev = left; | 223 | 1.12k | } |
Unexecuted instantiation: void mdds::st::detail::link_nodes<boost::intrusive_ptr<mdds::st::detail::node<unsigned int, mdds::flat_segment_tree<unsigned int, bool>::leaf_value_type> > >(boost::intrusive_ptr<mdds::st::detail::node<unsigned int, mdds::flat_segment_tree<unsigned int, bool>::leaf_value_type> >&, boost::intrusive_ptr<mdds::st::detail::node<unsigned int, mdds::flat_segment_tree<unsigned int, bool>::leaf_value_type> >&) void mdds::st::detail::link_nodes<boost::intrusive_ptr<mdds::st::detail::node<unsigned int, mdds::flat_segment_tree<unsigned int, std::__1::shared_ptr<libetonyek::IWORKStyle> >::leaf_value_type> > >(boost::intrusive_ptr<mdds::st::detail::node<unsigned int, mdds::flat_segment_tree<unsigned int, std::__1::shared_ptr<libetonyek::IWORKStyle> >::leaf_value_type> >&, boost::intrusive_ptr<mdds::st::detail::node<unsigned int, mdds::flat_segment_tree<unsigned int, std::__1::shared_ptr<libetonyek::IWORKStyle> >::leaf_value_type> >&) Line | Count | Source | 220 | 532 | { | 221 | 532 | left->next = right; | 222 | 532 | right->prev = left; | 223 | 532 | } |
|
224 | | |
225 | | template<typename T> |
226 | | class tree_builder |
227 | | { |
228 | | public: |
229 | | typedef typename T::node leaf_node; |
230 | | typedef typename leaf_node::node_ptr leaf_node_ptr; |
231 | | typedef typename T::nonleaf_node nonleaf_node; |
232 | | typedef std::vector<nonleaf_node> nonleaf_node_pool_type; |
233 | | |
234 | 129 | tree_builder(nonleaf_node_pool_type& pool) : m_pool(pool), m_pool_pos(pool.begin()), m_pool_pos_end(pool.end()) |
235 | 129 | {} |
236 | | |
237 | | nonleaf_node* build(const leaf_node_ptr& left_leaf_node) |
238 | 129 | { |
239 | 129 | if (!left_leaf_node) |
240 | | // The left leaf node is empty. Nothing to build. |
241 | 0 | return nullptr; |
242 | | |
243 | 129 | leaf_node_ptr node1 = left_leaf_node; |
244 | | |
245 | 129 | std::vector<nonleaf_node*> node_list; |
246 | 255 | while (true) |
247 | 255 | { |
248 | 255 | leaf_node_ptr node2 = node1->next; |
249 | 255 | nonleaf_node* parent_node = make_parent_node(node1.get(), node2.get()); |
250 | 255 | node_list.push_back(parent_node); |
251 | | |
252 | 255 | if (!node2 || !node2->next) |
253 | | // no more nodes. Break out of the loop. |
254 | 129 | break; |
255 | | |
256 | 126 | node1 = node2->next; |
257 | 126 | } |
258 | | |
259 | 129 | return build_tree_non_leaf(node_list); |
260 | 129 | } |
261 | | |
262 | | private: |
263 | | nonleaf_node* make_parent_node(node_base* node1, node_base* node2) |
264 | 381 | { |
265 | 381 | assert(m_pool_pos != m_pool_pos_end); |
266 | | |
267 | 381 | nonleaf_node* parent_node = &(*m_pool_pos); |
268 | 381 | ++m_pool_pos; |
269 | 381 | node1->parent = parent_node; |
270 | 381 | parent_node->left = node1; |
271 | 381 | if (node2) |
272 | 381 | { |
273 | 381 | node2->parent = parent_node; |
274 | 381 | parent_node->right = node2; |
275 | 381 | } |
276 | | |
277 | 381 | fill_nonleaf_parent_node(parent_node, node1, node2); |
278 | 381 | return parent_node; |
279 | 381 | } |
280 | | |
281 | | void fill_nonleaf_parent_node(nonleaf_node* parent_node, const node_base* left_node, const node_base* right_node) |
282 | 381 | { |
283 | | // Parent node should carry the range of all of its child nodes. |
284 | 381 | if (left_node) |
285 | 381 | { |
286 | 381 | parent_node->low = left_node->is_leaf ? static_cast<const leaf_node*>(left_node)->key |
287 | 381 | : static_cast<const nonleaf_node*>(left_node)->low; |
288 | 381 | } |
289 | 0 | else |
290 | 0 | { |
291 | | // Having a left node is prerequisite. |
292 | 0 | throw general_error("fill_nonleaf_parent_node: Having a left node is prerequisite."); |
293 | 0 | } |
294 | | |
295 | 381 | if (right_node) |
296 | 381 | { |
297 | 381 | if (right_node->is_leaf) |
298 | 255 | { |
299 | | // When the child nodes are leaf nodes, the upper bound |
300 | | // must be the value of the node that comes after the |
301 | | // right leaf node (if such node exists). |
302 | | |
303 | 255 | const auto* p = static_cast<const leaf_node*>(right_node); |
304 | 255 | if (p->next) |
305 | 126 | parent_node->high = p->next->key; |
306 | 129 | else |
307 | 129 | parent_node->high = p->key; |
308 | 255 | } |
309 | 126 | else |
310 | 126 | { |
311 | 126 | parent_node->high = static_cast<const nonleaf_node*>(right_node)->high; |
312 | 126 | } |
313 | 381 | } |
314 | 0 | else |
315 | 0 | { |
316 | 0 | parent_node->high = left_node->is_leaf ? static_cast<const leaf_node*>(left_node)->key |
317 | 0 | : static_cast<const nonleaf_node*>(left_node)->high; |
318 | 0 | } |
319 | 381 | } |
320 | | |
321 | | nonleaf_node* build_tree_non_leaf(const std::vector<nonleaf_node*>& node_list) |
322 | 255 | { |
323 | 255 | size_t node_count = node_list.size(); |
324 | 255 | if (node_count == 1) |
325 | 129 | { |
326 | 129 | return node_list.front(); |
327 | 129 | } |
328 | 126 | else if (node_count == 0) |
329 | 0 | return nullptr; |
330 | | |
331 | 126 | std::vector<nonleaf_node*> new_node_list; |
332 | 126 | nonleaf_node* node1 = nullptr; |
333 | 126 | typename std::vector<nonleaf_node*>::const_iterator it = node_list.begin(); |
334 | 126 | typename std::vector<nonleaf_node*>::const_iterator it_end = node_list.end(); |
335 | 378 | for (bool even_itr = false; it != it_end; ++it, even_itr = !even_itr) |
336 | 252 | { |
337 | 252 | if (even_itr) |
338 | 126 | { |
339 | 126 | nonleaf_node* node2 = *it; |
340 | 126 | nonleaf_node* parent_node = make_parent_node(node1, node2); |
341 | 126 | new_node_list.push_back(parent_node); |
342 | 126 | node1 = nullptr; |
343 | 126 | node2 = nullptr; |
344 | 126 | } |
345 | 126 | else |
346 | 126 | node1 = *it; |
347 | 252 | } |
348 | | |
349 | 126 | if (node1) |
350 | 0 | { |
351 | | // Un-paired node still needs a parent... |
352 | 0 | nonleaf_node* parent_node = make_parent_node(node1, nullptr); |
353 | 0 | new_node_list.push_back(parent_node); |
354 | 0 | } |
355 | | |
356 | | // Move up one level, and do the same procedure until the root node is reached. |
357 | 126 | return build_tree_non_leaf(new_node_list); |
358 | 255 | } |
359 | | |
360 | | nonleaf_node_pool_type& m_pool; |
361 | | typename nonleaf_node_pool_type::iterator m_pool_pos; |
362 | | typename nonleaf_node_pool_type::iterator m_pool_pos_end; |
363 | | }; |
364 | | |
365 | | template<typename KeyT, typename ValueT> |
366 | | void disconnect_all_nodes(node<KeyT, ValueT>* p) |
367 | 2.00k | { |
368 | 2.00k | if (!p) |
369 | 0 | return; |
370 | | |
371 | 2.00k | p->prev.reset(); |
372 | 2.00k | p->next.reset(); |
373 | 2.00k | p->parent = nullptr; |
374 | 2.00k | } void mdds::st::detail::disconnect_all_nodes<unsigned int, mdds::flat_segment_tree<unsigned int, bool>::leaf_value_type>(mdds::st::detail::node<unsigned int, mdds::flat_segment_tree<unsigned int, bool>::leaf_value_type>*) Line | Count | Source | 367 | 424 | { | 368 | 424 | if (!p) | 369 | 0 | return; | 370 | | | 371 | 424 | p->prev.reset(); | 372 | 424 | p->next.reset(); | 373 | 424 | p->parent = nullptr; | 374 | 424 | } |
void mdds::st::detail::disconnect_all_nodes<unsigned int, mdds::flat_segment_tree<unsigned int, float>::leaf_value_type>(mdds::st::detail::node<unsigned int, mdds::flat_segment_tree<unsigned int, float>::leaf_value_type>*) Line | Count | Source | 367 | 498 | { | 368 | 498 | if (!p) | 369 | 0 | return; | 370 | | | 371 | 498 | p->prev.reset(); | 372 | 498 | p->next.reset(); | 373 | 498 | p->parent = nullptr; | 374 | 498 | } |
void mdds::st::detail::disconnect_all_nodes<unsigned int, mdds::flat_segment_tree<unsigned int, std::__1::shared_ptr<libetonyek::IWORKStyle> >::leaf_value_type>(mdds::st::detail::node<unsigned int, mdds::flat_segment_tree<unsigned int, std::__1::shared_ptr<libetonyek::IWORKStyle> >::leaf_value_type>*) Line | Count | Source | 367 | 1.07k | { | 368 | 1.07k | if (!p) | 369 | 0 | return; | 370 | | | 371 | 1.07k | p->prev.reset(); | 372 | 1.07k | p->next.reset(); | 373 | 1.07k | p->parent = nullptr; | 374 | 1.07k | } |
|
375 | | |
376 | | template<typename KeyT, typename ValueT> |
377 | | void disconnect_leaf_nodes(node<KeyT, ValueT>* left_node, node<KeyT, ValueT>* right_node) |
378 | 971 | { |
379 | 971 | if (!left_node || !right_node) |
380 | 274 | return; |
381 | | |
382 | | // Go through all leaf nodes, and disconnect their links. |
383 | 697 | auto* cur_node = left_node; |
384 | 697 | do |
385 | 1.30k | { |
386 | 1.30k | auto* next_node = cur_node->next.get(); |
387 | 1.30k | disconnect_all_nodes(cur_node); |
388 | 1.30k | cur_node = next_node; |
389 | 1.30k | } while (cur_node != right_node); |
390 | | |
391 | 697 | disconnect_all_nodes(right_node); |
392 | 697 | } void mdds::st::detail::disconnect_leaf_nodes<unsigned int, mdds::flat_segment_tree<unsigned int, bool>::leaf_value_type>(mdds::st::detail::node<unsigned int, mdds::flat_segment_tree<unsigned int, bool>::leaf_value_type>*, mdds::st::detail::node<unsigned int, mdds::flat_segment_tree<unsigned int, bool>::leaf_value_type>*) Line | Count | Source | 378 | 212 | { | 379 | 212 | if (!left_node || !right_node) | 380 | 0 | return; | 381 | | | 382 | | // Go through all leaf nodes, and disconnect their links. | 383 | 212 | auto* cur_node = left_node; | 384 | 212 | do | 385 | 212 | { | 386 | 212 | auto* next_node = cur_node->next.get(); | 387 | 212 | disconnect_all_nodes(cur_node); | 388 | 212 | cur_node = next_node; | 389 | 212 | } while (cur_node != right_node); | 390 | | | 391 | 212 | disconnect_all_nodes(right_node); | 392 | 212 | } |
void mdds::st::detail::disconnect_leaf_nodes<unsigned int, mdds::flat_segment_tree<unsigned int, float>::leaf_value_type>(mdds::st::detail::node<unsigned int, mdds::flat_segment_tree<unsigned int, float>::leaf_value_type>*, mdds::st::detail::node<unsigned int, mdds::flat_segment_tree<unsigned int, float>::leaf_value_type>*) Line | Count | Source | 378 | 212 | { | 379 | 212 | if (!left_node || !right_node) | 380 | 0 | return; | 381 | | | 382 | | // Go through all leaf nodes, and disconnect their links. | 383 | 212 | auto* cur_node = left_node; | 384 | 212 | do | 385 | 286 | { | 386 | 286 | auto* next_node = cur_node->next.get(); | 387 | 286 | disconnect_all_nodes(cur_node); | 388 | 286 | cur_node = next_node; | 389 | 286 | } while (cur_node != right_node); | 390 | | | 391 | 212 | disconnect_all_nodes(right_node); | 392 | 212 | } |
void mdds::st::detail::disconnect_leaf_nodes<unsigned int, mdds::flat_segment_tree<unsigned int, std::__1::shared_ptr<libetonyek::IWORKStyle> >::leaf_value_type>(mdds::st::detail::node<unsigned int, mdds::flat_segment_tree<unsigned int, std::__1::shared_ptr<libetonyek::IWORKStyle> >::leaf_value_type>*, mdds::st::detail::node<unsigned int, mdds::flat_segment_tree<unsigned int, std::__1::shared_ptr<libetonyek::IWORKStyle> >::leaf_value_type>*) Line | Count | Source | 378 | 547 | { | 379 | 547 | if (!left_node || !right_node) | 380 | 274 | return; | 381 | | | 382 | | // Go through all leaf nodes, and disconnect their links. | 383 | 273 | auto* cur_node = left_node; | 384 | 273 | do | 385 | 805 | { | 386 | 805 | auto* next_node = cur_node->next.get(); | 387 | 805 | disconnect_all_nodes(cur_node); | 388 | 805 | cur_node = next_node; | 389 | 805 | } while (cur_node != right_node); | 390 | | | 391 | 273 | disconnect_all_nodes(right_node); | 392 | 273 | } |
|
393 | | |
394 | | template<typename KeyT, typename ValueT> |
395 | | size_t count_leaf_nodes(const node<KeyT, ValueT>* left_end, const node<KeyT, ValueT>* right_end) |
396 | 129 | { |
397 | 129 | size_t leaf_count = 1; |
398 | 129 | const auto* p = left_end; |
399 | 129 | const auto* p_end = right_end; |
400 | 510 | for (; p != p_end; p = p->next.get(), ++leaf_count) |
401 | 381 | ; |
402 | | |
403 | 129 | return leaf_count; |
404 | 129 | } |
405 | | |
406 | | inline size_t count_needed_nonleaf_nodes(size_t leaf_count) |
407 | 129 | { |
408 | 129 | size_t nonleaf_count = 0; |
409 | 384 | while (true) |
410 | 384 | { |
411 | 384 | if (leaf_count == 1) |
412 | 129 | break; |
413 | | |
414 | 255 | if ((leaf_count % 2) == 1) |
415 | | // Add one to make it an even number. |
416 | 0 | ++leaf_count; |
417 | | |
418 | 255 | leaf_count /= 2; |
419 | 255 | nonleaf_count += leaf_count; |
420 | 255 | } |
421 | | |
422 | 129 | return nonleaf_count; |
423 | 129 | } |
424 | | |
425 | | template<typename TraitsT> |
426 | | class tree_dumper |
427 | | { |
428 | | using node_list_type = std::vector<const node_base*>; |
429 | | using tree_type = typename TraitsT::tree_type; |
430 | | |
431 | | public: |
432 | | static size_t dump(std::ostream& os, const tree_type& tree, const node_base* root_node) |
433 | | { |
434 | | if (!root_node) |
435 | | return 0; |
436 | | |
437 | | node_list_type node_list; |
438 | | node_list.push_back(root_node); |
439 | | return dump_layer(os, tree, node_list, 0); |
440 | | } |
441 | | |
442 | | private: |
443 | | static size_t dump_layer( |
444 | | std::ostream& os, const tree_type& tree, const node_list_type& node_list, unsigned int level) |
445 | | { |
446 | | using leaf_type = typename TraitsT::leaf_type; |
447 | | using nonleaf_type = typename TraitsT::nonleaf_type; |
448 | | using to_string = typename TraitsT::to_string; |
449 | | |
450 | | if (node_list.empty()) |
451 | | return 0; |
452 | | |
453 | | size_t node_count = node_list.size(); |
454 | | |
455 | | bool is_leaf = node_list.front()->is_leaf; |
456 | | os << "level " << level << ':' << std::endl; |
457 | | os << " type: " << (is_leaf ? "leaf" : "non-leaf") << std::endl; |
458 | | os << " nodes:" << std::endl; |
459 | | |
460 | | node_list_type new_list; |
461 | | |
462 | | for (const node_base* p : node_list) |
463 | | { |
464 | | os << " - '"; |
465 | | |
466 | | if (!p) |
467 | | { |
468 | | os << "*'" << std::endl; |
469 | | continue; |
470 | | } |
471 | | |
472 | | if (p->is_leaf) |
473 | | { |
474 | | const auto* pl = static_cast<const leaf_type*>(p); |
475 | | os << to_string{tree}(*pl) << "'" << std::endl; |
476 | | continue; |
477 | | } |
478 | | |
479 | | const auto* pnl = static_cast<const nonleaf_type*>(p); |
480 | | os << to_string{tree}(*pnl) << "'" << std::endl; |
481 | | |
482 | | if (pnl->left) |
483 | | { |
484 | | new_list.push_back(pnl->left); |
485 | | if (pnl->right) |
486 | | new_list.push_back(pnl->right); |
487 | | } |
488 | | } |
489 | | |
490 | | if (!new_list.empty()) |
491 | | node_count += dump_layer(os, tree, new_list, level + 1); |
492 | | |
493 | | return node_count; |
494 | | } |
495 | | }; |
496 | | |
497 | | }}} // namespace mdds::st::detail |
498 | | |
499 | | #endif |