1 /*************************************************************************
3 * Copyright (c) 2008-2009 Kohei Yoshida
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
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
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.
26 ************************************************************************/
28 #ifndef __MDDS_NODE_HXX__
29 #define __MDDS_NODE_HXX__
35 //#define DEBUG_NODE_BASE 1
37 #define USE_INTRUSIVE_PTR 0
40 #include <boost/intrusive_ptr.hpp>
42 #include <boost/shared_ptr.hpp>
47 struct intrusive_ref_base
52 intrusive_ref_base() :
55 virtual ~intrusive_ref_base() {}
59 inline void intrusive_ptr_add_ref(intrusive_ref_base
* p
)
64 inline void intrusive_ptr_release(intrusive_ref_base
* p
)
72 #ifdef DEBUG_NODE_BASE
73 size_t node_instance_count
= 0;
78 typedef ::boost::intrusive_ptr
<node_base
> node_base_ptr
;
80 typedef ::boost::shared_ptr
<node_base
> node_base_ptr
;
83 struct node_base
: public intrusive_ref_base
85 static size_t get_instance_count()
87 #ifdef DEBUG_NODE_BASE
88 return node_instance_count
;
93 node_base_ptr parent
; /// parent node
94 node_base_ptr left
; /// left child node or previous sibling if it's a leaf node.
95 node_base_ptr right
; /// right child node or next sibling if it's aleaf node.
98 node_base(bool _is_leaf
) :
100 parent(static_cast<node_base
*>(NULL
)),
101 left(static_cast<node_base
*>(NULL
)),
102 right(static_cast<node_base
*>(NULL
)),
105 #ifdef DEBUG_NODE_BASE
106 ++node_instance_count
;
112 #ifdef DEBUG_NODE_BASE
113 --node_instance_count
;
117 // These methods are specific to concrete class implementation.
119 virtual void fill_nonleaf_value(const node_base_ptr
& left_node
, const node_base_ptr
& right_node
) = 0;
120 virtual void dump_value() const = 0;
121 virtual node_base
* create_new(bool leaf
) const = 0;
124 template<typename _NodePtr
>
125 void disconnect_node(_NodePtr p
)
135 template<typename _NodePtr
>
136 void link_nodes(_NodePtr
& left
, _NodePtr
& right
)
143 * Disconnect all non-leaf nodes so that their ref-counted instances will
144 * all get destroyed afterwards.
146 template<typename _NodePtr
>
147 void clear_tree(const _NodePtr
& node
)
155 node
->parent
.reset();
159 clear_tree(node
->left
);
160 clear_tree(node
->right
);
161 disconnect_node(node
.get());
164 template<typename _NodePtr
>
165 _NodePtr
make_parent_node(const _NodePtr
& node1
, const _NodePtr
& node2
)
167 _NodePtr
parent_node(node1
->create_new(false));
168 node1
->parent
= parent_node
;
169 parent_node
->left
= node1
;
172 node2
->parent
= parent_node
;
173 parent_node
->right
= node2
;
176 parent_node
->fill_nonleaf_value(node1
, node2
);
180 template<typename _NodePtr
>
181 _NodePtr
build_tree(const _NodePtr
& left_leaf_node
)
184 // The left leaf node is empty. Nothing to build.
187 _NodePtr node1
, node2
;
188 node1
= left_leaf_node
;
190 ::std::list
<_NodePtr
> node_list
;
193 node2
= node1
->right
;
194 _NodePtr parent_node
= make_parent_node(node1
, node2
);
195 node_list
.push_back(parent_node
);
197 if (!node2
|| !node2
->right
)
198 // no more nodes. Break out of the loop.
201 node1
= node2
->right
;
204 return build_tree_non_leaf(node_list
);
207 template<typename _NodePtr
>
208 _NodePtr
build_tree_non_leaf(const ::std::list
<_NodePtr
>& node_list
)
210 size_t node_count
= node_list
.size();
213 return node_list
.front();
215 else if (node_count
== 0)
218 ::std::list
<_NodePtr
> new_node_list
;
219 _NodePtr node_pair
[2];
220 typename ::std::list
<_NodePtr
>::const_iterator itr
= node_list
.begin();
221 typename ::std::list
<_NodePtr
>::const_iterator itrEnd
= node_list
.end();
222 for (bool even_itr
= false; itr
!= itrEnd
; ++itr
, even_itr
= !even_itr
)
224 node_pair
[even_itr
] = *itr
;
227 _NodePtr parent_node
= make_parent_node(node_pair
[0], node_pair
[1]);
228 node_pair
[0].reset();
229 node_pair
[1].reset();
230 new_node_list
.push_back(parent_node
);
236 // Un-paired node still needs a parent...
237 _NodePtr parent_node
= make_parent_node(node_pair
[0], _NodePtr());
238 node_pair
[0].reset();
239 node_pair
[1].reset();
240 new_node_list
.push_back(parent_node
);
243 // Move up one level, and do the same procedure until the root node is reached.
244 return build_tree_non_leaf(new_node_list
);
248 template<typename _NodePtr
>
249 size_t dump_tree_layer(const ::std::list
<_NodePtr
>& node_list
, unsigned int level
)
254 if (node_list
.empty())
257 size_t node_count
= node_list
.size();
259 bool isLeaf
= node_list
.front()->is_leaf
;
260 cout
<< "level " << level
<< " (" << (isLeaf
?"leaf":"non-leaf") << ")" << endl
;
262 ::std::list
<_NodePtr
> newList
;
263 typename ::std::list
<_NodePtr
>::const_iterator itr
= node_list
.begin(), itrEnd
= node_list
.end();
264 for (; itr
!= itrEnd
; ++itr
)
266 const _NodePtr
& p
= *itr
;
280 newList
.push_back(p
->left
);
282 newList
.push_back(p
->right
);
287 if (!newList
.empty())
288 node_count
+= dump_tree_layer(newList
, level
+1);
293 template<typename _NodePtr
>
294 size_t dump_tree(const _NodePtr
& root_node
)
299 ::std::list
<_NodePtr
> node_list
;
300 node_list
.push_back(root_node
);
301 return dump_tree_layer(node_list
, 0);