39struct nonleaf_node :
public node_base
41 using key_type = KeyT;
42 using nonleaf_value_type = ValueT;
44 nonleaf_value_type value_nonleaf;
53 std::is_nothrow_default_constructible_v<nonleaf_value_type>;
55 static constexpr bool nothrow_eq_comparable_v =
56 noexcept(std::declval<key_type>() == std::declval<key_type>()) &&
57 noexcept(std::declval<nonleaf_value_type>() == std::declval<nonleaf_value_type>());
67 nonleaf_node(
const nonleaf_node& r) : node_base(r), value_nonleaf(r.value_nonleaf), low(r.low),
high(r.
high)
79 value_nonleaf = r.value_nonleaf;
83 bool operator==(
const nonleaf_node& r)
const noexcept(nothrow_eq_comparable_v)
85 return low == r.low &&
high == r.high && value_nonleaf == r.value_nonleaf;
88 bool operator!=(
const nonleaf_node& r)
const noexcept(nothrow_eq_comparable_v)
90 return !operator==(r);
93 std::string to_string()
const
95 std::ostringstream os;
96 os <<
"[" << low <<
"-" <<
high <<
")";
105struct node : node_base
107 using key_type = KeyT;
108 using leaf_value_type = ValueT;
109 using node_ptr = boost::intrusive_ptr<node>;
111 static size_t get_instance_count()
113#ifdef MDDS_DEBUG_NODE_BASE
114 return node_instance_count;
120 leaf_value_type value_leaf;
129 static constexpr bool nothrow_default_constructible_v = std::is_nothrow_default_constructible_v<key_type> &&
130 std::is_nothrow_default_constructible_v<leaf_value_type> &&
131 std::is_nothrow_default_constructible_v<node_ptr>;
133 static constexpr bool nothrow_eq_comparable_v =
134 noexcept(std::declval<key_type>() == std::declval<key_type>()) &&
135 noexcept(std::declval<leaf_value_type>() == std::declval<leaf_value_type>());
138 node() noexcept(nothrow_default_constructible_v) : node_base(true)
140#ifdef MDDS_DEBUG_NODE_BASE
141 ++node_instance_count;
149 node(
const node& r) : node_base(r), key(r.key)
151#ifdef MDDS_DEBUG_NODE_BASE
152 ++node_instance_count;
154 value_leaf = r.value_leaf;
166 value_leaf = r.value_leaf;
172#ifdef MDDS_DEBUG_NODE_BASE
173 --node_instance_count;
177 bool operator==(
const node& r)
const noexcept(nothrow_eq_comparable_v)
179 return key == r.key && value_leaf == r.value_leaf;
182 bool operator!=(
const node& r)
const noexcept(nothrow_eq_comparable_v)
184 return !operator==(r);
187 std::string to_string()
const
189 std::ostringstream os;
190 os <<
"[" << key <<
"]";
220 typedef typename T::node leaf_node;
221 typedef typename leaf_node::node_ptr leaf_node_ptr;
222 typedef typename T::nonleaf_node nonleaf_node;
223 typedef std::vector<nonleaf_node> nonleaf_node_pool_type;
225 tree_builder(nonleaf_node_pool_type& pool) : m_pool(pool), m_pool_pos(pool.begin()), m_pool_pos_end(pool.end())
228 nonleaf_node* build(
const leaf_node_ptr& left_leaf_node)
234 leaf_node_ptr node1 = left_leaf_node;
236 std::vector<nonleaf_node*> node_list;
239 leaf_node_ptr node2 = node1->next;
240 nonleaf_node* parent_node = make_parent_node(node1.get(), node2.get());
241 node_list.push_back(parent_node);
243 if (!node2 || !node2->next)
250 return build_tree_non_leaf(node_list);
256 assert(m_pool_pos != m_pool_pos_end);
258 nonleaf_node* parent_node = &(*m_pool_pos);
260 node1->parent = parent_node;
261 parent_node->left = node1;
264 node2->parent = parent_node;
265 parent_node->right = node2;
268 fill_nonleaf_parent_node(parent_node, node1, node2);
272 void fill_nonleaf_parent_node(nonleaf_node* parent_node,
const node_base* left_node,
const node_base* right_node)
277 parent_node->low = left_node->
is_leaf ?
static_cast<const leaf_node*
>(left_node)->key
278 :
static_cast<const nonleaf_node*
>(left_node)->low;
283 throw general_error(
"fill_nonleaf_parent_node: Having a left node is prerequisite.");
294 const auto* p =
static_cast<const leaf_node*
>(right_node);
296 parent_node->high = p->next->key;
298 parent_node->high = p->key;
302 parent_node->high =
static_cast<const nonleaf_node*
>(right_node)->high;
307 parent_node->high = left_node->
is_leaf ?
static_cast<const leaf_node*
>(left_node)->key
308 :
static_cast<const nonleaf_node*
>(left_node)->high;
312 nonleaf_node* build_tree_non_leaf(
const std::vector<nonleaf_node*>& node_list)
314 size_t node_count = node_list.size();
317 return node_list.front();
319 else if (node_count == 0)
322 std::vector<nonleaf_node*> new_node_list;
323 nonleaf_node* node1 =
nullptr;
324 typename std::vector<nonleaf_node*>::const_iterator it = node_list.begin();
325 typename std::vector<nonleaf_node*>::const_iterator it_end = node_list.end();
326 for (
bool even_itr =
false; it != it_end; ++it, even_itr = !even_itr)
330 nonleaf_node* node2 = *it;
331 nonleaf_node* parent_node = make_parent_node(node1, node2);
332 new_node_list.push_back(parent_node);
343 nonleaf_node* parent_node = make_parent_node(node1,
nullptr);
344 new_node_list.push_back(parent_node);
348 return build_tree_non_leaf(new_node_list);
351 nonleaf_node_pool_type& m_pool;
352 typename nonleaf_node_pool_type::iterator m_pool_pos;
353 typename nonleaf_node_pool_type::iterator m_pool_pos_end;
386SizeT count_leaf_nodes(
const node<KeyT, ValueT>* left_end,
const node<KeyT, ValueT>* right_end)
noexcept(
420 using node_list_type = std::vector<const node_base*>;
421 using tree_type =
typename TraitsT::tree_type;
424 static size_t dump(std::ostream& os,
const tree_type& tree,
const node_base* root_node)
429 node_list_type node_list;
430 node_list.push_back(root_node);
431 return dump_layer(os, tree, node_list, 0);
435 static size_t dump_layer(
436 std::ostream& os,
const tree_type& tree,
const node_list_type& node_list,
unsigned int level)
438 using leaf_type =
typename TraitsT::leaf_type;
439 using nonleaf_type =
typename TraitsT::nonleaf_type;
440 using to_string =
typename TraitsT::to_string;
442 if (node_list.empty())
445 size_t node_count = node_list.size();
447 bool is_leaf = node_list.front()->is_leaf;
448 os <<
"level " << level <<
':' << std::endl;
449 os <<
" type: " << (is_leaf ?
"leaf" :
"non-leaf") << std::endl;
450 os <<
" nodes:" << std::endl;
452 node_list_type new_list;
460 os <<
"*'" << std::endl;
466 const auto* pl =
static_cast<const leaf_type*
>(p);
467 os << to_string{tree}(*pl) <<
"'" << std::endl;
471 const auto* pnl =
static_cast<const nonleaf_type*
>(p);
472 os << to_string{tree}(*pnl) <<
"'" << std::endl;
476 new_list.push_back(pnl->left);
478 new_list.push_back(pnl->right);
482 if (!new_list.empty())
483 node_count += dump_layer(os, tree, new_list, level + 1);