/src/mdds-1.3.1/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 <iostream> |
32 | | #include <vector> |
33 | | #include <cassert> |
34 | | |
35 | | #include <boost/intrusive_ptr.hpp> |
36 | | |
37 | | namespace mdds { namespace __st { |
38 | | |
39 | | #ifdef MDDS_DEBUG_NODE_BASE |
40 | | size_t node_instance_count = 0; |
41 | | #endif |
42 | | |
43 | | struct node_base |
44 | | { |
45 | | node_base* parent; /// parent nonleaf_node |
46 | | bool is_leaf; |
47 | | |
48 | 2.06k | node_base(bool _is_leaf) : parent(nullptr), is_leaf(_is_leaf) {} |
49 | 870 | node_base(const node_base& r) : parent(nullptr), is_leaf(r.is_leaf) {} |
50 | | }; |
51 | | |
52 | | template<typename T> |
53 | | struct nonleaf_node : public node_base |
54 | | { |
55 | | typedef typename T::nonleaf_value_type nonleaf_value_type; |
56 | | typedef typename T::fill_nonleaf_value_handler fill_nonleaf_value_handler; |
57 | | typedef typename T::init_handler init_handler; |
58 | | typedef typename T::dispose_handler dispose_handler; |
59 | | #ifdef MDDS_UNIT_TEST |
60 | | typedef typename T::to_string_handler to_string_handler; |
61 | | #endif |
62 | | nonleaf_value_type value_nonleaf; |
63 | | |
64 | | node_base* left; /// left child nonleaf_node |
65 | | node_base* right; /// right child nonleaf_node |
66 | | |
67 | | private: |
68 | | fill_nonleaf_value_handler _hdl_fill_nonleaf; |
69 | | init_handler _hdl_init; |
70 | | dispose_handler _hdl_dispose; |
71 | | #ifdef MDDS_UNIT_TEST |
72 | | to_string_handler _hdl_to_string; |
73 | | #endif |
74 | | |
75 | | public: |
76 | | nonleaf_node() : |
77 | 310 | node_base(false), |
78 | 310 | left(nullptr), |
79 | 310 | right(nullptr) |
80 | 310 | { |
81 | 310 | _hdl_init(*this); |
82 | 310 | } |
83 | | |
84 | | /** |
85 | | * When copying nonleaf_node, only the stored values should be copied. |
86 | | * Connections to the parent, left and right nodes must not be copied. |
87 | | */ |
88 | | nonleaf_node(const nonleaf_node& r) : |
89 | 0 | node_base(r), |
90 | 0 | left(nullptr), |
91 | 0 | right(nullptr) |
92 | 0 | { |
93 | 0 | value_nonleaf = r.value_nonleaf; |
94 | 0 | } |
95 | | |
96 | | /** |
97 | | * Like the copy constructor, only the stored values should be copied. |
98 | | */ |
99 | | nonleaf_node& operator=(const nonleaf_node& r) |
100 | | { |
101 | | if (this == &r) |
102 | | // assignment to self. |
103 | | return *this; |
104 | | |
105 | | value_nonleaf = r.value_nonleaf; |
106 | | return *this; |
107 | | } |
108 | | |
109 | | ~nonleaf_node() |
110 | 310 | { |
111 | 310 | dispose(); |
112 | 310 | } Unexecuted instantiation: mdds::__st::nonleaf_node<mdds::flat_segment_tree<unsigned int, bool> >::~nonleaf_node() mdds::__st::nonleaf_node<mdds::flat_segment_tree<unsigned int, std::__1::shared_ptr<libetonyek::IWORKStyle> > >::~nonleaf_node() Line | Count | Source | 110 | 310 | { | 111 | 310 | dispose(); | 112 | 310 | } |
Unexecuted instantiation: mdds::__st::nonleaf_node<mdds::flat_segment_tree<unsigned int, float> >::~nonleaf_node() |
113 | | |
114 | | void dispose() |
115 | 310 | { |
116 | 310 | _hdl_dispose(*this); |
117 | 310 | } Unexecuted instantiation: mdds::__st::nonleaf_node<mdds::flat_segment_tree<unsigned int, bool> >::dispose() mdds::__st::nonleaf_node<mdds::flat_segment_tree<unsigned int, std::__1::shared_ptr<libetonyek::IWORKStyle> > >::dispose() Line | Count | Source | 115 | 310 | { | 116 | 310 | _hdl_dispose(*this); | 117 | 310 | } |
Unexecuted instantiation: mdds::__st::nonleaf_node<mdds::flat_segment_tree<unsigned int, float> >::dispose() |
118 | | |
119 | | bool equals(const nonleaf_node& r) const |
120 | | { |
121 | | return value_nonleaf == r.value_nonleaf; |
122 | | } |
123 | | |
124 | | void fill_nonleaf_value(const node_base* left_node, const node_base* right_node) |
125 | 310 | { |
126 | 310 | _hdl_fill_nonleaf(*this, left_node, right_node); |
127 | 310 | } |
128 | | |
129 | | #ifdef MDDS_UNIT_TEST |
130 | | void dump_value() const |
131 | | { |
132 | | ::std::cout << _hdl_to_string(*this); |
133 | | } |
134 | | |
135 | | ::std::string to_string() const |
136 | | { |
137 | | return _hdl_to_string(*this); |
138 | | } |
139 | | #endif |
140 | | }; |
141 | | |
142 | | template<typename T> |
143 | | struct node : public node_base |
144 | | { |
145 | | typedef ::boost::intrusive_ptr<node> node_ptr; |
146 | | |
147 | | typedef typename T::leaf_value_type leaf_value_type; |
148 | | typedef typename T::init_handler init_handler; |
149 | | typedef typename T::dispose_handler dispose_handler; |
150 | | #ifdef MDDS_UNIT_TEST |
151 | | typedef typename T::to_string_handler to_string_handler; |
152 | | #endif |
153 | | |
154 | | static size_t get_instance_count() |
155 | | { |
156 | | #ifdef MDDS_DEBUG_NODE_BASE |
157 | | return node_instance_count; |
158 | | #else |
159 | | return 0; |
160 | | #endif |
161 | | } |
162 | | |
163 | | leaf_value_type value_leaf; |
164 | | |
165 | | node_ptr prev; /// previous sibling leaf node. |
166 | | node_ptr next; /// next sibling leaf node. |
167 | | |
168 | | size_t refcount; |
169 | | private: |
170 | | init_handler _hdl_init; |
171 | | dispose_handler _hdl_dispose; |
172 | | #ifdef MDDS_UNIT_TEST |
173 | | to_string_handler _hdl_to_string; |
174 | | #endif |
175 | | |
176 | | public: |
177 | 1.75k | node() : node_base(true), refcount(0) |
178 | 1.75k | { |
179 | | #ifdef MDDS_DEBUG_NODE_BASE |
180 | | ++node_instance_count; |
181 | | #endif |
182 | 1.75k | _hdl_init(*this); |
183 | 1.75k | } mdds::__st::node<mdds::flat_segment_tree<unsigned int, float> >::node() Line | Count | Source | 177 | 930 | node() : node_base(true), refcount(0) | 178 | 930 | { | 179 | | #ifdef MDDS_DEBUG_NODE_BASE | 180 | | ++node_instance_count; | 181 | | #endif | 182 | 930 | _hdl_init(*this); | 183 | 930 | } |
mdds::__st::node<mdds::flat_segment_tree<unsigned int, bool> >::node() Line | Count | Source | 177 | 392 | node() : node_base(true), refcount(0) | 178 | 392 | { | 179 | | #ifdef MDDS_DEBUG_NODE_BASE | 180 | | ++node_instance_count; | 181 | | #endif | 182 | 392 | _hdl_init(*this); | 183 | 392 | } |
mdds::__st::node<mdds::flat_segment_tree<unsigned int, std::__1::shared_ptr<libetonyek::IWORKStyle> > >::node() Line | Count | Source | 177 | 434 | node() : node_base(true), refcount(0) | 178 | 434 | { | 179 | | #ifdef MDDS_DEBUG_NODE_BASE | 180 | | ++node_instance_count; | 181 | | #endif | 182 | 434 | _hdl_init(*this); | 183 | 434 | } |
|
184 | | |
185 | | /** |
186 | | * When copying node, only the stored values should be copied. |
187 | | * Connections to the parent, left and right nodes must not be copied. |
188 | | */ |
189 | 870 | node(const node& r) : node_base(r), refcount(0) |
190 | 870 | { |
191 | | #ifdef MDDS_DEBUG_NODE_BASE |
192 | | ++node_instance_count; |
193 | | #endif |
194 | 870 | value_leaf = r.value_leaf; |
195 | 870 | } |
196 | | |
197 | | /** |
198 | | * Like the copy constructor, only the stored values should be copied. |
199 | | */ |
200 | | node& operator=(const node& r) |
201 | | { |
202 | | if (this == &r) |
203 | | // assignment to self. |
204 | | return *this; |
205 | | |
206 | | value_leaf = r.value_leaf; |
207 | | return *this; |
208 | | } |
209 | | |
210 | | ~node() |
211 | 2.62k | { |
212 | | #ifdef MDDS_DEBUG_NODE_BASE |
213 | | --node_instance_count; |
214 | | #endif |
215 | 2.62k | dispose(); |
216 | 2.62k | } mdds::__st::node<mdds::flat_segment_tree<unsigned int, bool> >::~node() Line | Count | Source | 211 | 392 | { | 212 | | #ifdef MDDS_DEBUG_NODE_BASE | 213 | | --node_instance_count; | 214 | | #endif | 215 | 392 | dispose(); | 216 | 392 | } |
mdds::__st::node<mdds::flat_segment_tree<unsigned int, std::__1::shared_ptr<libetonyek::IWORKStyle> > >::~node() Line | Count | Source | 211 | 1.30k | { | 212 | | #ifdef MDDS_DEBUG_NODE_BASE | 213 | | --node_instance_count; | 214 | | #endif | 215 | 1.30k | dispose(); | 216 | 1.30k | } |
mdds::__st::node<mdds::flat_segment_tree<unsigned int, float> >::~node() Line | Count | Source | 211 | 930 | { | 212 | | #ifdef MDDS_DEBUG_NODE_BASE | 213 | | --node_instance_count; | 214 | | #endif | 215 | 930 | dispose(); | 216 | 930 | } |
|
217 | | |
218 | | void dispose() |
219 | 2.62k | { |
220 | 2.62k | _hdl_dispose(*this); |
221 | 2.62k | } mdds::__st::node<mdds::flat_segment_tree<unsigned int, bool> >::dispose() Line | Count | Source | 219 | 392 | { | 220 | 392 | _hdl_dispose(*this); | 221 | 392 | } |
mdds::__st::node<mdds::flat_segment_tree<unsigned int, std::__1::shared_ptr<libetonyek::IWORKStyle> > >::dispose() Line | Count | Source | 219 | 1.30k | { | 220 | 1.30k | _hdl_dispose(*this); | 221 | 1.30k | } |
mdds::__st::node<mdds::flat_segment_tree<unsigned int, float> >::dispose() Line | Count | Source | 219 | 930 | { | 220 | 930 | _hdl_dispose(*this); | 221 | 930 | } |
|
222 | | |
223 | | bool equals(const node& r) const |
224 | | { |
225 | | return value_leaf == r.value_leaf; |
226 | | } |
227 | | |
228 | | #ifdef MDDS_UNIT_TEST |
229 | | void dump_value() const |
230 | | { |
231 | | ::std::cout << _hdl_to_string(*this); |
232 | | } |
233 | | |
234 | | ::std::string to_string() const |
235 | | { |
236 | | return _hdl_to_string(*this); |
237 | | } |
238 | | #endif |
239 | | }; |
240 | | |
241 | | template<typename T> |
242 | | inline void intrusive_ptr_add_ref(node<T>* p) |
243 | 15.4k | { |
244 | 15.4k | ++p->refcount; |
245 | 15.4k | } void mdds::__st::intrusive_ptr_add_ref<mdds::flat_segment_tree<unsigned int, std::__1::shared_ptr<libetonyek::IWORKStyle> > >(mdds::__st::node<mdds::flat_segment_tree<unsigned int, std::__1::shared_ptr<libetonyek::IWORKStyle> > >*) Line | Count | Source | 243 | 5.62k | { | 244 | 5.62k | ++p->refcount; | 245 | 5.62k | } |
void mdds::__st::intrusive_ptr_add_ref<mdds::flat_segment_tree<unsigned int, float> >(mdds::__st::node<mdds::flat_segment_tree<unsigned int, float> >*) Line | Count | Source | 243 | 6.58k | { | 244 | 6.58k | ++p->refcount; | 245 | 6.58k | } |
void mdds::__st::intrusive_ptr_add_ref<mdds::flat_segment_tree<unsigned int, bool> >(mdds::__st::node<mdds::flat_segment_tree<unsigned int, bool> >*) Line | Count | Source | 243 | 3.24k | { | 244 | 3.24k | ++p->refcount; | 245 | 3.24k | } |
|
246 | | |
247 | | template<typename T> |
248 | | inline void intrusive_ptr_release(node<T>* p) |
249 | 15.4k | { |
250 | 15.4k | --p->refcount; |
251 | 15.4k | if (!p->refcount) |
252 | 2.62k | delete p; |
253 | 15.4k | } void mdds::__st::intrusive_ptr_release<mdds::flat_segment_tree<unsigned int, bool> >(mdds::__st::node<mdds::flat_segment_tree<unsigned int, bool> >*) Line | Count | Source | 249 | 3.24k | { | 250 | 3.24k | --p->refcount; | 251 | 3.24k | if (!p->refcount) | 252 | 392 | delete p; | 253 | 3.24k | } |
void mdds::__st::intrusive_ptr_release<mdds::flat_segment_tree<unsigned int, std::__1::shared_ptr<libetonyek::IWORKStyle> > >(mdds::__st::node<mdds::flat_segment_tree<unsigned int, std::__1::shared_ptr<libetonyek::IWORKStyle> > >*) Line | Count | Source | 249 | 5.62k | { | 250 | 5.62k | --p->refcount; | 251 | 5.62k | if (!p->refcount) | 252 | 1.30k | delete p; | 253 | 5.62k | } |
void mdds::__st::intrusive_ptr_release<mdds::flat_segment_tree<unsigned int, float> >(mdds::__st::node<mdds::flat_segment_tree<unsigned int, float> >*) Line | Count | Source | 249 | 6.58k | { | 250 | 6.58k | --p->refcount; | 251 | 6.58k | if (!p->refcount) | 252 | 930 | delete p; | 253 | 6.58k | } |
|
254 | | |
255 | | template<typename T> |
256 | | void link_nodes(typename node<T>::node_ptr& left, typename node<T>::node_ptr& right) |
257 | 1.50k | { |
258 | 1.50k | left->next = right; |
259 | 1.50k | right->prev = left; |
260 | 1.50k | } void mdds::__st::link_nodes<mdds::flat_segment_tree<unsigned int, float> >(mdds::__st::node<mdds::flat_segment_tree<unsigned int, float> >::node_ptr&, mdds::__st::node<mdds::flat_segment_tree<unsigned int, float> >::node_ptr&) Line | Count | Source | 257 | 1.07k | { | 258 | 1.07k | left->next = right; | 259 | 1.07k | right->prev = left; | 260 | 1.07k | } |
Unexecuted instantiation: void mdds::__st::link_nodes<mdds::flat_segment_tree<unsigned int, bool> >(mdds::__st::node<mdds::flat_segment_tree<unsigned int, bool> >::node_ptr&, mdds::__st::node<mdds::flat_segment_tree<unsigned int, bool> >::node_ptr&) void mdds::__st::link_nodes<mdds::flat_segment_tree<unsigned int, std::__1::shared_ptr<libetonyek::IWORKStyle> > >(mdds::__st::node<mdds::flat_segment_tree<unsigned int, std::__1::shared_ptr<libetonyek::IWORKStyle> > >::node_ptr&, mdds::__st::node<mdds::flat_segment_tree<unsigned int, std::__1::shared_ptr<libetonyek::IWORKStyle> > >::node_ptr&) Line | Count | Source | 257 | 432 | { | 258 | 432 | left->next = right; | 259 | 432 | right->prev = left; | 260 | 432 | } |
|
261 | | |
262 | | template<typename T> |
263 | | class tree_builder |
264 | | { |
265 | | public: |
266 | | typedef mdds::__st::node<T> leaf_node; |
267 | | typedef typename mdds::__st::node<T>::node_ptr leaf_node_ptr; |
268 | | typedef mdds::__st::nonleaf_node<T> nonleaf_node; |
269 | | typedef std::vector<nonleaf_node> nonleaf_node_pool_type; |
270 | | |
271 | | tree_builder(nonleaf_node_pool_type& pool) : |
272 | 104 | m_pool(pool), m_pool_pos(pool.begin()), m_pool_pos_end(pool.end()) {} |
273 | | |
274 | | nonleaf_node* build(const leaf_node_ptr& left_leaf_node) |
275 | 104 | { |
276 | 104 | if (!left_leaf_node) |
277 | | // The left leaf node is empty. Nothing to build. |
278 | 0 | return nullptr; |
279 | | |
280 | 104 | leaf_node_ptr node1 = left_leaf_node; |
281 | | |
282 | 104 | std::vector<nonleaf_node*> node_list; |
283 | 207 | while (true) |
284 | 207 | { |
285 | 207 | leaf_node_ptr node2 = node1->next; |
286 | 207 | nonleaf_node* parent_node = make_parent_node(node1.get(), node2.get()); |
287 | 207 | node_list.push_back(parent_node); |
288 | | |
289 | 207 | if (!node2 || !node2->next) |
290 | | // no more nodes. Break out of the loop. |
291 | 104 | break; |
292 | | |
293 | 103 | node1 = node2->next; |
294 | 103 | } |
295 | | |
296 | 104 | return build_tree_non_leaf(node_list); |
297 | 104 | } |
298 | | |
299 | | private: |
300 | | |
301 | | nonleaf_node* make_parent_node(node_base* node1, node_base* node2) |
302 | 310 | { |
303 | 310 | assert(m_pool_pos != m_pool_pos_end); |
304 | | |
305 | 310 | nonleaf_node* parent_node = &(*m_pool_pos); |
306 | 310 | ++m_pool_pos; |
307 | 310 | node1->parent = parent_node; |
308 | 310 | parent_node->left = node1; |
309 | 310 | if (node2) |
310 | 310 | { |
311 | 310 | node2->parent = parent_node; |
312 | 310 | parent_node->right = node2; |
313 | 310 | } |
314 | | |
315 | 310 | parent_node->fill_nonleaf_value(node1, node2); |
316 | 310 | return parent_node; |
317 | 310 | } |
318 | | |
319 | | nonleaf_node* build_tree_non_leaf(const std::vector<nonleaf_node*>& node_list) |
320 | 207 | { |
321 | 207 | size_t node_count = node_list.size(); |
322 | 207 | if (node_count == 1) |
323 | 104 | { |
324 | 104 | return node_list.front(); |
325 | 104 | } |
326 | 103 | else if (node_count == 0) |
327 | 0 | return nullptr; |
328 | | |
329 | 103 | std::vector<nonleaf_node*> new_node_list; |
330 | 103 | nonleaf_node* node1 = nullptr; |
331 | 103 | typename std::vector<nonleaf_node*>::const_iterator it = node_list.begin(); |
332 | 103 | typename std::vector<nonleaf_node*>::const_iterator it_end = node_list.end(); |
333 | 309 | for (bool even_itr = false; it != it_end; ++it, even_itr = !even_itr) |
334 | 206 | { |
335 | 206 | if (even_itr) |
336 | 103 | { |
337 | 103 | nonleaf_node* node2 = *it; |
338 | 103 | nonleaf_node* parent_node = make_parent_node(node1, node2); |
339 | 103 | new_node_list.push_back(parent_node); |
340 | 103 | node1 = nullptr; |
341 | 103 | node2 = nullptr; |
342 | 103 | } |
343 | 103 | else |
344 | 103 | node1 = *it; |
345 | 206 | } |
346 | | |
347 | 103 | if (node1) |
348 | 0 | { |
349 | | // Un-paired node still needs a parent... |
350 | 0 | nonleaf_node* parent_node = make_parent_node(node1, nullptr); |
351 | 0 | new_node_list.push_back(parent_node); |
352 | 0 | } |
353 | | |
354 | | // Move up one level, and do the same procedure until the root node is reached. |
355 | 103 | return build_tree_non_leaf(new_node_list); |
356 | 207 | } |
357 | | |
358 | | nonleaf_node_pool_type& m_pool; |
359 | | typename nonleaf_node_pool_type::iterator m_pool_pos; |
360 | | typename nonleaf_node_pool_type::iterator m_pool_pos_end; |
361 | | }; |
362 | | |
363 | | |
364 | | template<typename T> |
365 | | void disconnect_all_nodes(node<T>* p) |
366 | 2.16k | { |
367 | 2.16k | if (!p) |
368 | 0 | return; |
369 | | |
370 | 2.16k | p->prev.reset(); |
371 | 2.16k | p->next.reset(); |
372 | 2.16k | p->parent = nullptr; |
373 | 2.16k | } void mdds::__st::disconnect_all_nodes<mdds::flat_segment_tree<unsigned int, bool> >(mdds::__st::node<mdds::flat_segment_tree<unsigned int, bool> >*) Line | Count | Source | 366 | 392 | { | 367 | 392 | if (!p) | 368 | 0 | return; | 369 | | | 370 | 392 | p->prev.reset(); | 371 | 392 | p->next.reset(); | 372 | 392 | p->parent = nullptr; | 373 | 392 | } |
void mdds::__st::disconnect_all_nodes<mdds::flat_segment_tree<unsigned int, float> >(mdds::__st::node<mdds::flat_segment_tree<unsigned int, float> >*) Line | Count | Source | 366 | 468 | { | 367 | 468 | if (!p) | 368 | 0 | return; | 369 | | | 370 | 468 | p->prev.reset(); | 371 | 468 | p->next.reset(); | 372 | 468 | p->parent = nullptr; | 373 | 468 | } |
void mdds::__st::disconnect_all_nodes<mdds::flat_segment_tree<unsigned int, std::__1::shared_ptr<libetonyek::IWORKStyle> > >(mdds::__st::node<mdds::flat_segment_tree<unsigned int, std::__1::shared_ptr<libetonyek::IWORKStyle> > >*) Line | Count | Source | 366 | 1.30k | { | 367 | 1.30k | if (!p) | 368 | 0 | return; | 369 | | | 370 | 1.30k | p->prev.reset(); | 371 | 1.30k | p->next.reset(); | 372 | 1.30k | p->parent = nullptr; | 373 | 1.30k | } |
|
374 | | |
375 | | template<typename T> |
376 | | void disconnect_leaf_nodes(node<T>* left_node, node<T>* right_node) |
377 | 828 | { |
378 | 828 | if (!left_node || !right_node) |
379 | 0 | return; |
380 | | |
381 | | // Go through all leaf nodes, and disconnect their links. |
382 | 828 | node<T>* cur_node = left_node; |
383 | 828 | do |
384 | 1.33k | { |
385 | 1.33k | node<T>* next_node = cur_node->next.get(); |
386 | 1.33k | disconnect_all_nodes(cur_node); |
387 | 1.33k | cur_node = next_node; |
388 | 1.33k | } |
389 | 1.33k | while (cur_node != right_node); |
390 | | |
391 | 828 | disconnect_all_nodes(right_node); |
392 | 828 | } void mdds::__st::disconnect_leaf_nodes<mdds::flat_segment_tree<unsigned int, bool> >(mdds::__st::node<mdds::flat_segment_tree<unsigned int, bool> >*, mdds::__st::node<mdds::flat_segment_tree<unsigned int, bool> >*) Line | Count | Source | 377 | 196 | { | 378 | 196 | if (!left_node || !right_node) | 379 | 0 | return; | 380 | | | 381 | | // Go through all leaf nodes, and disconnect their links. | 382 | 196 | node<T>* cur_node = left_node; | 383 | 196 | do | 384 | 196 | { | 385 | 196 | node<T>* next_node = cur_node->next.get(); | 386 | 196 | disconnect_all_nodes(cur_node); | 387 | 196 | cur_node = next_node; | 388 | 196 | } | 389 | 196 | while (cur_node != right_node); | 390 | | | 391 | 196 | disconnect_all_nodes(right_node); | 392 | 196 | } |
void mdds::__st::disconnect_leaf_nodes<mdds::flat_segment_tree<unsigned int, float> >(mdds::__st::node<mdds::flat_segment_tree<unsigned int, float> >*, mdds::__st::node<mdds::flat_segment_tree<unsigned int, float> >*) Line | Count | Source | 377 | 196 | { | 378 | 196 | if (!left_node || !right_node) | 379 | 0 | return; | 380 | | | 381 | | // Go through all leaf nodes, and disconnect their links. | 382 | 196 | node<T>* cur_node = left_node; | 383 | 196 | do | 384 | 272 | { | 385 | 272 | node<T>* next_node = cur_node->next.get(); | 386 | 272 | disconnect_all_nodes(cur_node); | 387 | 272 | cur_node = next_node; | 388 | 272 | } | 389 | 272 | while (cur_node != right_node); | 390 | | | 391 | 196 | disconnect_all_nodes(right_node); | 392 | 196 | } |
void mdds::__st::disconnect_leaf_nodes<mdds::flat_segment_tree<unsigned int, std::__1::shared_ptr<libetonyek::IWORKStyle> > >(mdds::__st::node<mdds::flat_segment_tree<unsigned int, std::__1::shared_ptr<libetonyek::IWORKStyle> > >*, mdds::__st::node<mdds::flat_segment_tree<unsigned int, std::__1::shared_ptr<libetonyek::IWORKStyle> > >*) Line | Count | Source | 377 | 436 | { | 378 | 436 | if (!left_node || !right_node) | 379 | 0 | return; | 380 | | | 381 | | // Go through all leaf nodes, and disconnect their links. | 382 | 436 | node<T>* cur_node = left_node; | 383 | 436 | do | 384 | 868 | { | 385 | 868 | node<T>* next_node = cur_node->next.get(); | 386 | 868 | disconnect_all_nodes(cur_node); | 387 | 868 | cur_node = next_node; | 388 | 868 | } | 389 | 868 | while (cur_node != right_node); | 390 | | | 391 | 436 | disconnect_all_nodes(right_node); | 392 | 436 | } |
|
393 | | |
394 | | template<typename T> |
395 | | size_t count_leaf_nodes(const node<T>* left_end, const node<T>* right_end) |
396 | 104 | { |
397 | 104 | size_t leaf_count = 1; |
398 | 104 | const node<T>* p = left_end; |
399 | 104 | const node<T>* p_end = right_end; |
400 | 414 | for (; p != p_end; p = p->next.get(), ++leaf_count) |
401 | 310 | ; |
402 | | |
403 | 104 | return leaf_count; |
404 | 104 | } |
405 | | |
406 | | inline size_t count_needed_nonleaf_nodes(size_t leaf_count) |
407 | 104 | { |
408 | 104 | size_t nonleaf_count = 0; |
409 | 311 | while (true) |
410 | 311 | { |
411 | 311 | if (leaf_count == 1) |
412 | 104 | break; |
413 | | |
414 | 207 | if ((leaf_count % 2) == 1) |
415 | | // Add one to make it an even number. |
416 | 0 | ++leaf_count; |
417 | | |
418 | 207 | leaf_count /= 2; |
419 | 207 | nonleaf_count += leaf_count; |
420 | 207 | } |
421 | | |
422 | 104 | return nonleaf_count; |
423 | 104 | } |
424 | | |
425 | | #ifdef MDDS_UNIT_TEST |
426 | | |
427 | | template<typename _Leaf, typename _NonLeaf> |
428 | | class tree_dumper |
429 | | { |
430 | | typedef std::vector<const node_base*> node_list_type; |
431 | | |
432 | | public: |
433 | | static size_t dump(const node_base* root_node) |
434 | | { |
435 | | if (!root_node) |
436 | | return 0; |
437 | | |
438 | | node_list_type node_list; |
439 | | node_list.push_back(root_node); |
440 | | return dump_layer(node_list, 0); |
441 | | } |
442 | | |
443 | | private: |
444 | | static size_t dump_layer(const node_list_type& node_list, unsigned int level) |
445 | | { |
446 | | using ::std::cout; |
447 | | using ::std::endl; |
448 | | |
449 | | if (node_list.empty()) |
450 | | return 0; |
451 | | |
452 | | size_t node_count = node_list.size(); |
453 | | |
454 | | bool is_leaf = node_list.front()->is_leaf; |
455 | | cout << "level " << level << " (" << (is_leaf?"leaf":"non-leaf") << ")" << endl; |
456 | | |
457 | | node_list_type new_list; |
458 | | typename node_list_type::const_iterator it = node_list.begin(), it_end = node_list.end(); |
459 | | for (; it != it_end; ++it) |
460 | | { |
461 | | const node_base* p = *it; |
462 | | if (!p) |
463 | | { |
464 | | cout << "(x) "; |
465 | | continue; |
466 | | } |
467 | | |
468 | | if (p->is_leaf) |
469 | | static_cast<const _Leaf*>(p)->dump_value(); |
470 | | else |
471 | | static_cast<const _NonLeaf*>(p)->dump_value(); |
472 | | |
473 | | if (p->is_leaf) |
474 | | continue; |
475 | | |
476 | | if (static_cast<const _NonLeaf*>(p)->left) |
477 | | { |
478 | | new_list.push_back(static_cast<const _NonLeaf*>(p)->left); |
479 | | if (static_cast<const _NonLeaf*>(p)->right) |
480 | | new_list.push_back(static_cast<const _NonLeaf*>(p)->right); |
481 | | } |
482 | | } |
483 | | cout << endl; |
484 | | |
485 | | if (!new_list.empty()) |
486 | | node_count += dump_layer(new_list, level+1); |
487 | | |
488 | | return node_count; |
489 | | } |
490 | | }; |
491 | | |
492 | | #endif |
493 | | |
494 | | }} |
495 | | |
496 | | #endif |