TPIE

11a2c2d
btree.h
1 // -*- mode: c++; tab-width: 4; indent-tabs-mode: t; eval: (progn (c-set-style "stroustrup") (c-set-offset 'innamespace 0)); -*-
2 // vi:set ts=4 sts=4 sw=4 noet :
3 // Copyright 2014 The TPIE development team
4 //
5 // This file is part of TPIE.
6 //
7 // TPIE is free software: you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License as published by the
9 // Free Software Foundation, either version 3 of the License, or (at your
10 // option) any later version.
11 //
12 // TPIE is distributed in the hope that it will be useful, but WITHOUT ANY
13 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 // License for more details.
16 //
17 // You should have received a copy of the GNU Lesser General Public License
18 // along with TPIE. If not, see <http://www.gnu.org/licenses/>
19 
20 #ifndef _TPIE_BTREE_TREE_H_
21 #define _TPIE_BTREE_TREE_H_
22 
23 #include <tpie/portability.h>
24 #include <tpie/btree/base.h>
25 #include <tpie/btree/node.h>
26 #include <tpie/memory.h>
27 #include <cstddef>
28 #include <vector>
29 
30 namespace tpie {
31 namespace bbits {
32 
37 template <typename T, typename O>
38 class tree {
39 public:
40  typedef tree_state<T, O> state_type;
41 
42  static const bool is_internal = state_type::is_internal;
43  static const bool is_static = state_type::is_static;
44  static const bool is_ordered = state_type::is_ordered;
45 
46  typedef typename state_type::augmenter_type augmenter_type;
47 
51  typedef typename state_type::value_type value_type;
52  typedef typename state_type::keyextract_type keyextract_type;
53 
54  typedef typename state_type::augment_type augment_type;
55 
56 
60  typedef typename state_type::key_type key_type;
61 
62  typedef typename O::C comp_type;
63 
64  typedef typename state_type::store_type store_type;
65 
66 
71 
75  typedef typename store_type::size_type size_type;
76 
81 private:
82  typedef typename store_type::leaf_type leaf_type;
83  typedef typename store_type::internal_type internal_type;
84 
85 
86  size_t count_child(internal_type node, size_t i, leaf_type) const {
87  return m_state.store().count_child_leaf(node, i);
88  }
89 
90  size_t count_child(internal_type node, size_t i, internal_type) const {
91  return m_state.store().count_child_internal(node, i);
92  }
93 
94  internal_type get_child(internal_type node, size_t i, internal_type) const {
95  return m_state.store().get_child_internal(node, i);
96  }
97 
98  leaf_type get_child(internal_type node, size_t i, leaf_type) const {
99  return m_state.store().get_child_leaf(node, i);
100  }
101 
102  template <bool upper_bound = false, typename K>
103  leaf_type find_leaf(std::vector<internal_type> & path, K k) const {
104  path.clear();
105  if (m_state.store().height() == 1) return m_state.store().get_root_leaf();
106  internal_type n = m_state.store().get_root_internal();
107  for (size_t i=2;; ++i) {
108  path.push_back(n);
109  for (size_t j=0; ; ++j) {
110  if (j+1 == m_state.store().count(n) ||
111  (upper_bound
112  ? m_comp(k, m_state.min_key(n, j+1))
113  : !m_comp(m_state.min_key(n, j+1), k))) {
114  if (i == m_state.store().height()) return m_state.store().get_child_leaf(n, j);
115  n = m_state.store().get_child_internal(n, j);
116  break;
117  }
118  }
119  }
120  }
121 
122  void augment(leaf_type l, internal_type p) {
123  m_state.store().set_augment(l, p, m_state.m_augmenter(node_type(&m_state, l)));
124  }
125 
126  void augment(value_type, leaf_type) {
127  }
128 
129 
130  void augment(internal_type l, internal_type p) {
131  m_state.store().set_augment(l, p, m_state.m_augmenter(node_type(&m_state, l)));
132  }
133 
134  size_t max_size(internal_type) const throw() {
135  return m_state.store().max_internal_size();
136  }
137 
138  size_t max_size(leaf_type) const throw() {
139  return m_state.store().max_leaf_size();
140  }
141 
142  size_t min_size(internal_type) const throw() {
143  return m_state.store().min_internal_size();
144  }
145 
146  size_t min_size(leaf_type) const throw() {
147  return m_state.store().min_leaf_size();
148  }
149 
150  template <typename NT, typename VT>
151  void insert_part(NT n, VT v, size_t index) {
152  size_t z = m_state.store().count(n);
153  size_t i = z;
154  while (i > index) {
155  m_state.store().move(n, i-1, n, i);
156  --i;
157  }
158  m_state.store().set(n, i, v);
159  m_state.store().set_count(n, z+1);
160  augment(v, n);
161  }
162 
163  template <typename CT, typename NT>
164  NT split_and_insert(CT c, NT left, size_t index) {
165  tp_assert(m_state.store().count(left) == max_size(left), "Node not full");
166 
167  size_t left_size = max_size(left)/2;
168  size_t right_size = max_size(left)-left_size;
169  NT right = m_state.store().create(left);
170  for (size_t i=0; i < right_size; ++i)
171  m_state.store().move(left, left_size+i, right, i);
172  m_state.store().set_count(left, left_size);
173  m_state.store().set_count(right, right_size);
174 
175  if (index <= left_size)
176  insert_part(left, c, index);
177  else
178  insert_part(right, c, index - left_size);
179  return right;
180  }
181 
182  void augment_path(leaf_type) {
183  //NOOP
184  }
185 
186  void augment_path(std::vector<internal_type> & path) {
187  while (path.size() >= 2) {
188  internal_type c=path.back();
189  path.pop_back();
190  augment(c, path.back());
191  }
192  }
193 
194  void augment_path(const internal_type * path, size_t level) {
195  while (level >= 1) {
196  augment(path[level], path[level-1]);
197  --level;
198  }
199  }
200 
201 
202  template <typename CT, typename PT>
203  bool remove_fixup_round(CT c, PT p) {
204  size_t z=m_state.store().count(c);
205  size_t i=m_state.store().index(c, p);
206  if (i != 0 && count_child(p, i-1, c) > min_size(c)) {
207  //We can steel a value from left
208  CT left = get_child(p, i-1, c);
209  size_t left_size = m_state.store().count(left);
210  for (size_t j=0; j < z; ++j)
211  m_state.store().move(c, z-j-1, c, z-j);
212  m_state.store().move(left, left_size-1, c, 0);
213  m_state.store().set_count(left, left_size-1);
214  m_state.store().set_count(c, z+1);
215  augment(c, p);
216  augment(left, p);
217  return true;
218  }
219 
220 
221  if (i +1 != m_state.store().count(p) &&
222  count_child(p, i+1, c) > min_size(c)) {
223  // We can steel from right
224  CT right = get_child(p, i+1, c);
225  size_t right_size = m_state.store().count(right);
226  m_state.store().move(right, 0, c, z);
227  for (size_t i=0; i+1 < right_size ; ++i)
228  m_state.store().move(right, i+1, right, i);
229  m_state.store().set_count(right, right_size-1);
230  m_state.store().set_count(c, z+1);
231  augment(c, p);
232  augment(right, p);
233  return true;
234  }
235 
236  CT c1;
237  CT c2;
238  if (i == 0) {
239  c1 = c;
240  c2 = get_child(p, i+1, c);
241  } else {
242  c1 = get_child(p, i-1, c);
243  c2 = c;
244  }
245 
246  //Merge l2 into l1
247  size_t z1 = m_state.store().count(c1);
248  size_t z2 = m_state.store().count(c2);
249  for (size_t i=0; i < z2; ++i)
250  m_state.store().move(c2, i, c1, i+z1);
251  m_state.store().set_count(c1, z1+z2);
252  m_state.store().set_count(c2, 0);
253 
254  // And remove c2 from p
255  size_t id = m_state.store().index(c2, p);
256  size_t z_ = m_state.store().count(p) -1;
257  for (; id != z_; ++id)
258  m_state.store().move(p, id+1, p, id);
259  m_state.store().set_count(p, z_);
260  m_state.store().destroy(c2);
261 
262  augment(c1, p);
263  return z_ >= min_size(p);
264  }
265 
266 public:
270  iterator begin() const {
271  iterator i(&m_state);
272  i.goto_begin();
273  return i;
274  }
275 
279  iterator end() const {
280  iterator i(&m_state);
281  i.goto_end();
282  return i;
283  }
284 
285 
286  template <typename NT>
287  void createNewRoot(NT left, NT right) {
288  internal_type i = m_state.store().create_internal();
289  m_state.store().set_count(i, 2);
290  m_state.store().set(i, 0, left);
291  m_state.store().set(i, 1, right);
292  m_state.store().set_root(i);
293  m_state.store().set_height(m_state.store().height()+1);
294  augment(left, i);
295  augment(right, i);
296  }
297 
301  template <typename X=enab>
302  void insert_before(value_type v, const iterator & itr, enable<X, !is_static> =enab()) {
303  m_state.store().set_size(m_state.store().size() + 1);
304 
305  // Handle the special case of the empty tree
306  if (m_state.store().height() == 0) {
307  leaf_type n = m_state.store().create_leaf();
308  m_state.store().set_count(n, 1);
309  m_state.store().set(n, 0, v);
310  m_state.store().set_height(1);
311  m_state.store().set_root(n);
312  return;
313  }
314 
315  const auto path = itr.m_path.data();
316  auto index = itr.index();
317  auto level = itr.m_path.size();
318 
319  //If there is room in the leaf
320  if (m_state.store().count(itr.m_leaf) != m_state.store().max_leaf_size()) {
321  insert_part(itr.m_leaf, v, index);
322  if (level != 0) {
323  augment(itr.m_leaf, path[level-1]);
324  augment_path(path, level-1);
325  }
326  return;
327  }
328 
329  // We split the leaf
330  leaf_type l2 = split_and_insert(v, itr.m_leaf, index);
331 
332  // If the leaf was a root leaf we create a new root
333  if (level == 0) {
334  createNewRoot(itr.m_leaf, l2);
335  return;
336  }
337  --level;
338  index = m_state.store().index(itr.m_leaf, path[level]) + 1;
339 
340  augment(itr.m_leaf, path[level]);
341 
342  //If there is room in the parent to insert the extra leave
343  if (m_state.store().count(path[level]) != m_state.store().max_internal_size()) {
344  insert_part(path[level], l2, index);
345  augment_path(path, level);
346  return;
347  }
348 
349  internal_type n2 = split_and_insert(l2, path[level], index);
350  while (level != 0) {
351  --level;
352  index = m_state.store().index(path[level+1], path[level]) + 1;
353  augment(path[level+1], path[level]);
354  if (m_state.store().count(path[level]) != m_state.store().max_internal_size()) {
355  insert_part(path[level], n2, index);
356  augment_path(path, level);
357  return;
358  }
359  n2 = split_and_insert(n2, path[level], index);
360  }
361 
362  //We need a new root
363  createNewRoot(path[0], n2);
364  }
365 
366 
370  template <typename X=enab>
371  void insert(value_type v, enable<X, !is_static> =enab()) {
372  insert_before(v, upper_bound(m_state.m_augmenter.m_key_extract(v)));
373  }
374 
378  template <typename K, typename X=enab>
379  iterator find(K v, enable<X, is_ordered> =enab()) const {
380  iterator itr(&m_state);
381 
382  if(m_state.store().height() == 0) {
383  itr.goto_end();
384  return itr;
385  }
386 
387  std::vector<internal_type> path;
388  leaf_type l = find_leaf<true>(path, v);
389 
390  size_t i=0;
391  size_t z = m_state.store().count(l);
392  while (true) {
393  if (i == z) {
394  itr.goto_end();
395  return itr;
396  }
397  if (!m_comp(m_state.min_key(l, i), v) &&
398  !m_comp(v, m_state.min_key(l, i))) break;
399  ++i;
400  }
401  itr.goto_item(path, l, i);
402  return itr;
403  }
404 
409  template <typename K, typename X=enab>
410  iterator lower_bound(K v, enable<X, is_ordered> =enab()) const {
411  iterator itr(&m_state);
412  if (m_state.store().height() == 0) {
413  itr.goto_end();
414  return itr;
415  }
416 
417  std::vector<internal_type> path;
418  leaf_type l = find_leaf(path, v);
419 
420  const size_t z = m_state.store().count(l);
421  for (size_t i = 0 ; i < z ; ++i) {
422  if (!m_comp(m_state.min_key(l, i), v)) {
423  itr.goto_item(path, l, i);
424  return itr;
425  }
426  }
427  itr.goto_item(path, l, z-1);
428  return ++itr;
429  }
430 
435  template <typename K, typename X=enab>
436  iterator upper_bound(K v, enable<X, is_ordered> =enab()) const {
437  iterator itr(&m_state);
438  if (m_state.store().height() == 0) {
439  itr.goto_end();
440  return itr;
441  }
442 
443  std::vector<internal_type> path;
444  leaf_type l = find_leaf<true>(path, v);
445 
446  const size_t z = m_state.store().count(l);
447  for (size_t i = 0 ; i < z ; ++i) {
448  if (m_comp(v, m_state.min_key(l, i))) {
449  itr.goto_item(path, l, i);
450  return itr;
451  }
452  }
453  itr.goto_item(path, l, z-1);
454  return ++itr;
455  }
456 
460  template <typename X=enab>
461  void erase(const iterator & itr, enable<X, !is_static> =enab()) {
462  std::vector<internal_type> path=itr.m_path;
463  leaf_type l = itr.m_leaf;
464 
465  size_t z = m_state.store().count(l);
466  size_t i = itr.m_index;
467 
468  m_state.store().set_size(m_state.store().size()-1);
469  --z;
470  for (; i != z; ++i)
471  m_state.store().move(l, i+1, l, i);
472  m_state.store().set_count(l, z);
473 
474  // If we still have a large enough size
475  if (z >= m_state.store().min_leaf_size()) {
476  // We are the lone root
477  if (path.empty()) {
478  augment_path(l);
479  return;
480  }
481  augment(l, path.back());
482  augment_path(path);
483  return;
484  }
485 
486  // We are too small but the root
487  if (path.empty()) {
488  // We are now the empty tree
489  if (z == 0) {
490  m_state.store().destroy(l);
491  m_state.store().set_height(0);
492  return;
493  }
494  augment_path(l);
495  return;
496  }
497 
498  // Steal or merge
499  if (remove_fixup_round(l, path.back())) {
500  augment_path(path);
501  return;
502  }
503 
504  // If l is now the only child of the root, make l the root
505  if (path.size() == 1) {
506  if (m_state.store().count(path.back()) == 1) {
507  l = m_state.store().get_child_leaf(path.back(), 0);
508  m_state.store().set_count(path.back(), 0);
509  m_state.store().destroy(path.back());
510  m_state.store().set_height(1);
511  m_state.store().set_root(l);
512  augment_path(l);
513  return;
514  }
515  augment_path(path);
516  return;
517  }
518 
519  while (true) {
520  // We need to handle the parent
521  internal_type p = path.back();
522  path.pop_back();
523  if (remove_fixup_round(p, path.back())) {
524  augment_path(path);
525  return;
526  }
527 
528  if (path.size() == 1) {
529  if (m_state.store().count(path.back()) == 1) {
530  p = m_state.store().get_child_internal(path.back(), 0);
531  m_state.store().set_count(path.back(), 0);
532  m_state.store().destroy(path.back());
533  m_state.store().set_height(m_state.store().height()-1);
534  m_state.store().set_root(p);
535  path.clear();
536  path.push_back(p);
537  augment_path(path);
538  return;
539  }
540  augment_path(path);
541  return;
542  }
543  }
544  }
545 
549  template <typename X=enab>
550  size_type erase(key_type v, enable<X, !is_static && is_ordered> =enab()) {
551  size_type count = 0;
552  iterator i = find(v);
553  while(i != end()) {
554  erase(i);
555  ++count;
556  i = find(v);
557  }
558 
559  return count;
560  }
561 
566  node_type root() const {
567  if (m_state.store().height() == 1) return node_type(&m_state, m_state.store().get_root_leaf());
568  return node_type(&m_state, m_state.store().get_root_internal());
569  }
570 
574  size_type size() const throw() {
575  return m_state.store().size();
576  }
577 
581  bool empty() const throw() {
582  return m_state.store().size() == 0;
583  }
584 
585  void set_metadata(const std::string & data) {
586  m_state.store().set_metadata(data);
587  }
588 
589  std::string get_metadata() {
590  return m_state.store().get_metadata();
591  }
592 
596  template <typename X=enab>
597  explicit tree(std::string path, comp_type comp=comp_type(), augmenter_type augmenter=augmenter_type(), enable<X, !is_internal> =enab() ):
598  m_state(store_type(path), std::move(augmenter), keyextract_type()),
599  m_comp(comp) {}
600 
604  template <typename X=enab>
605  explicit tree(comp_type comp=comp_type(),
606  augmenter_type augmenter=augmenter_type(),
608  enable<X, is_internal> =enab() ):
609  m_state(store_type(bucket), std::move(augmenter), keyextract_type()),
610  m_comp(comp) {}
611 
612  friend class bbits::builder<T, O>;
613 
614  const comp_type & comp() const {
615  return m_comp;
616  }
617 
618 private:
619  explicit tree(state_type state, comp_type comp):
620  m_state(std::move(state)),
621  m_comp(comp) {}
622 
623  state_type m_state;
624  comp_type m_comp;
625 };
626 
627 } //namespace bbits
628 
629 template <typename T, typename ... Opts>
630 using btree = bbits::tree<T, typename bbits::OptComp<Opts...>::type>;
631 
632 } //namespace tpie
633 #endif /*_TPIE_BTREE_TREE_H_*/
tpie::bbits::tree::size
size_type size() const
Return the number of elements in the tree
Definition: btree.h:574
tpie::bbits::tree::insert_before
void insert_before(value_type v, const iterator &itr, enable< X, !is_static >=enab())
Insert given value into the btree before iterator.
Definition: btree.h:302
tpie::bbits::tree::root
node_type root() const
Return the root node.
Definition: btree.h:566
tpie::bbits::tree::node_type
btree_node< state_type > node_type
Type of node wrapper.
Definition: btree.h:70
portability.h
tpie::btree_iterator
Definition: base.h:225
tpie::bbits::tree::erase
void erase(const iterator &itr, enable< X, !is_static >=enab())
remove item at iterator
Definition: btree.h:461
tpie::bbits::tree::iterator
btree_iterator< state_type > iterator
Iterator type.
Definition: btree.h:80
tpie::bbits::tree::tree
tree(std::string path, comp_type comp=comp_type(), augmenter_type augmenter=augmenter_type(), enable< X, !is_internal >=enab())
Construct a btree with the given storage.
Definition: btree.h:597
tpie::bbits::tree::begin
iterator begin() const
Returns an iterator pointing to the beginning of the tree.
Definition: btree.h:270
tpie::bbits::tree::tree
tree(comp_type comp=comp_type(), augmenter_type augmenter=augmenter_type(), memory_bucket_ref bucket=memory_bucket_ref(), enable< X, is_internal >=enab())
Construct a btree with the given storage.
Definition: btree.h:605
tpie::bbits::tree::size_type
store_type::size_type size_type
Type of the size.
Definition: btree.h:75
tpie::memory_bucket_ref
Class storring a reference to a memory bucket.
Definition: memory.h:334
tpie::bbits::enab
Definition: base.h:262
tpie::bbits::tree::empty
bool empty() const
Check if the tree is empty.
Definition: btree.h:581
tpie::bbits::tree::insert
void insert(value_type v, enable< X, !is_static >=enab())
Insert given value into the btree.
Definition: btree.h:371
tp_assert
#define tp_assert(condition, message)
Definition: tpie_assert.h:65
tpie::bbits::tree::erase
size_type erase(key_type v, enable< X, !is_static &&is_ordered >=enab())
remove all items with given key
Definition: btree.h:550
tpie::bbits::tree::end
iterator end() const
Returns an iterator pointing to the end of the tree.
Definition: btree.h:279
tpie::bbits::tree::upper_bound
iterator upper_bound(K v, enable< X, is_ordered >=enab()) const
Return an interator to the first element that is "greater" than the given key.
Definition: btree.h:436
tpie::bbits::tree::lower_bound
iterator lower_bound(K v, enable< X, is_ordered >=enab()) const
Return an interator to the first element that is "not less" than the given key.
Definition: btree.h:410
tpie::bbits::tree::find
iterator find(K v, enable< X, is_ordered >=enab()) const
Return an iterator to the first item with the given key.
Definition: btree.h:379
tpie::bbits::tree::key_type
state_type::key_type key_type
The type of key used.
Definition: btree.h:60
tpie::bbits::tree::value_type
state_type::value_type value_type
Type of value stored.
Definition: btree.h:51
memory.h
tpie::btree_node
Type that is useful for navigating a btree.
Definition: base.h:221
tpie
Definition: access_type.h:26
tpie::bbits::builder
Augmented btree builder.
Definition: base.h:248