TPIE

2362a60
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 N>
151  N split(N left) {
152  tp_assert(m_state.store().count(left) == max_size(left), "Node not full");
153  size_t left_size = max_size(left)/2;
154  size_t right_size = max_size(left)-left_size;
155  N right = m_state.store().create(left);
156  for (size_t i=0; i < right_size; ++i)
157  m_state.store().move(left, left_size+i, right, i);
158  m_state.store().set_count(left, left_size);
159  m_state.store().set_count(right, right_size);
160  return right;
161  };
162 
163  template <typename NT, typename VT>
164  void insert_part(NT n, VT v) {
165  size_t z = m_state.store().count(n);
166  size_t i = z;
167  for (;i > 0 && m_comp(m_state.min_key(v), m_state.min_key(n, i-1)); --i)
168  m_state.store().move(n, i-1, n, i);
169  m_state.store().set(n, i, v);
170  m_state.store().set_count(n, z+1);
171  augment(v, n);
172  }
173 
174  template <typename CT, typename NT>
175  NT split_and_insert(CT c, NT p) {
176  tp_assert(m_state.store().count(p) == max_size(p), "Node not full");
177  NT p2=split(p);
178  if (m_comp(m_state.min_key(c), m_state.min_key(p2)))
179  insert_part(p, c);
180  else
181  insert_part(p2, c);
182  return p2;
183  }
184 
185  void augment_path(leaf_type) {
186  //NOOP
187  }
188 
189  void augment_path(std::vector<internal_type> & path) {
190  while (path.size() >= 2) {
191  internal_type c=path.back();
192  path.pop_back();
193  augment(c, path.back());
194  }
195  path.pop_back();
196  }
197 
198  template <typename CT, typename PT>
199  bool remove_fixup_round(CT c, PT p) {
200  size_t z=m_state.store().count(c);
201  size_t i=m_state.store().index(c, p);
202  if (i != 0 && count_child(p, i-1, c) > min_size(c)) {
203  //We can steel a value from left
204  CT left = get_child(p, i-1, c);
205  size_t left_size = m_state.store().count(left);
206  for (size_t j=0; j < z; ++j)
207  m_state.store().move(c, z-j-1, c, z-j);
208  m_state.store().move(left, left_size-1, c, 0);
209  m_state.store().set_count(left, left_size-1);
210  m_state.store().set_count(c, z+1);
211  augment(c, p);
212  augment(left, p);
213  return true;
214  }
215 
216 
217  if (i +1 != m_state.store().count(p) &&
218  count_child(p, i+1, c) > min_size(c)) {
219  // We can steel from right
220  CT right = get_child(p, i+1, c);
221  size_t right_size = m_state.store().count(right);
222  m_state.store().move(right, 0, c, z);
223  for (size_t i=0; i+1 < right_size ; ++i)
224  m_state.store().move(right, i+1, right, i);
225  m_state.store().set_count(right, right_size-1);
226  m_state.store().set_count(c, z+1);
227  augment(c, p);
228  augment(right, p);
229  return true;
230  }
231 
232  CT c1;
233  CT c2;
234  if (i == 0) {
235  c1 = c;
236  c2 = get_child(p, i+1, c);
237  } else {
238  c1 = get_child(p, i-1, c);
239  c2 = c;
240  }
241 
242  //Merge l2 into l1
243  size_t z1 = m_state.store().count(c1);
244  size_t z2 = m_state.store().count(c2);
245  for (size_t i=0; i < z2; ++i)
246  m_state.store().move(c2, i, c1, i+z1);
247  m_state.store().set_count(c1, z1+z2);
248  m_state.store().set_count(c2, 0);
249 
250  // And remove c2 from p
251  size_t id = m_state.store().index(c2, p);
252  size_t z_ = m_state.store().count(p) -1;
253  for (; id != z_; ++id)
254  m_state.store().move(p, id+1, p, id);
255  m_state.store().set_count(p, z_);
256  m_state.store().destroy(c2);
257 
258  augment(c1, p);
259  return z_ >= min_size(p);
260  }
261 
262 public:
266  iterator begin() const {
267  iterator i(&m_state);
268  i.goto_begin();
269  return i;
270  }
271 
275  iterator end() const {
276  iterator i(&m_state);
277  i.goto_end();
278  return i;
279  }
280 
284  template <typename X=enab>
285  void insert(value_type v, enable<X, !is_static> =enab()) {
286  m_state.store().set_size(m_state.store().size() + 1);
287 
288  // Handle the special case of the empty tree
289  if (m_state.store().height() == 0) {
290  leaf_type n = m_state.store().create_leaf();
291  m_state.store().set_count(n, 1);
292  m_state.store().set(n, 0, v);
293  m_state.store().set_height(1);
294  m_state.store().set_root(n);
295  augment_path(n);
296  return;
297  }
298 
299  std::vector<internal_type> path;
300 
301  // Find the leaf contaning the value
302  leaf_type l = find_leaf(path, m_state.min_key(v));
303  //If there is room in the leaf
304  if (m_state.store().count(l) != m_state.store().max_leaf_size()) {
305  insert_part(l, v);
306  if (!path.empty()) augment(l, path.back());
307  augment_path(path);
308  return;
309  }
310 
311  // We split the leaf
312  leaf_type l2 = split_and_insert(v, l);
313 
314  // If the leaf was a root leef we create a new root
315  if (path.empty()) {
316  internal_type i=m_state.store().create_internal();
317  m_state.store().set_count(i, 2);
318  m_state.store().set(i, 0, l);
319  m_state.store().set(i, 1, l2);
320  m_state.store().set_root(i);
321  m_state.store().set_height(m_state.store().height()+1);
322  augment(l, i);
323  augment(l2, i);
324  path.push_back(i);
325  augment_path(path);
326  return;
327  }
328 
329  internal_type p = path.back();
330  augment(l, p);
331 
332  //If there is room in the parent to insert the extra leave
333  if (m_state.store().count(p) != m_state.store().max_internal_size()) {
334  insert_part(p, l2);
335  augment_path(path);
336  return;
337  }
338 
339  path.pop_back();
340  internal_type n2 = split_and_insert(l2, p);
341  internal_type n1 = p;
342 
343  while (!path.empty()) {
344  internal_type p = path.back();
345  augment(n1, p);
346  if (m_state.store().count(p) != m_state.store().max_internal_size()) {
347  insert_part(p, n2);
348  augment_path(path);
349  return;
350  }
351  path.pop_back();
352  n2 = split_and_insert(n2, p);
353  n1 = p;
354 
355  }
356 
357  //We need a new root
358  internal_type i=m_state.store().create_internal();
359  m_state.store().set_count(i, 2);
360  m_state.store().set(i, 0, n1);
361  m_state.store().set(i, 1, n2);
362  m_state.store().set_root(i);
363  m_state.store().set_height(m_state.store().height()+1);
364  augment(n1, i);
365  augment(n2, i);
366  path.push_back(i);
367  augment_path(path);
368  }
369 
373  template <typename K, typename X=enab>
374  iterator find(K v, enable<X, is_ordered> =enab()) const {
375  iterator itr(&m_state);
376 
377  if(m_state.store().height() == 0) {
378  itr.goto_end();
379  return itr;
380  }
381 
382  std::vector<internal_type> path;
383  leaf_type l = find_leaf<true>(path, v);
384 
385  size_t i=0;
386  size_t z = m_state.store().count(l);
387  while (true) {
388  if (i == z) {
389  itr.goto_end();
390  return itr;
391  }
392  if (!m_comp(m_state.min_key(l, i), v) &&
393  !m_comp(v, m_state.min_key(l, i))) break;
394  ++i;
395  }
396  itr.goto_item(path, l, i);
397  return itr;
398  }
399 
404  template <typename K, typename X=enab>
405  iterator lower_bound(K v, enable<X, is_ordered> =enab()) const {
406  iterator itr(&m_state);
407  if (m_state.store().height() == 0) {
408  itr.goto_end();
409  return itr;
410  }
411 
412  std::vector<internal_type> path;
413  leaf_type l = find_leaf(path, v);
414 
415  const size_t z = m_state.store().count(l);
416  for (size_t i = 0 ; i < z ; ++i) {
417  if (!m_comp(m_state.min_key(l, i), v)) {
418  itr.goto_item(path, l, i);
419  return itr;
420  }
421  }
422  itr.goto_item(path, l, z-1);
423  return ++itr;
424  }
425 
430  template <typename K, typename X=enab>
431  iterator upper_bound(K v, enable<X, is_ordered> =enab()) const {
432  iterator itr(&m_state);
433  if (m_state.store().height() == 0) {
434  itr.goto_end();
435  return itr;
436  }
437 
438  std::vector<internal_type> path;
439  leaf_type l = find_leaf<true>(path, v);
440 
441  const size_t z = m_state.store().count(l);
442  for (size_t i = 0 ; i < z ; ++i) {
443  if (m_comp(v, m_state.min_key(l, i))) {
444  itr.goto_item(path, l, i);
445  return itr;
446  }
447  }
448  itr.goto_item(path, l, z-1);
449  return ++itr;
450  }
451 
455  template <typename X=enab>
456  void erase(const iterator & itr, enable<X, !is_static> =enab()) {
457  std::vector<internal_type> path=itr.m_path;
458  leaf_type l = itr.m_leaf;
459 
460  size_t z = m_state.store().count(l);
461  size_t i = itr.m_index;
462 
463  m_state.store().set_size(m_state.store().size()-1);
464  --z;
465  for (; i != z; ++i)
466  m_state.store().move(l, i+1, l, i);
467  m_state.store().set_count(l, z);
468 
469  // If we still have a large enough size
470  if (z >= m_state.store().min_leaf_size()) {
471  // We are the lone root
472  if (path.empty()) {
473  augment_path(l);
474  return;
475  }
476  augment(l, path.back());
477  augment_path(path);
478  return;
479  }
480 
481  // We are too small but the root
482  if (path.empty()) {
483  // We are now the empty tree
484  if (z == 0) {
485  m_state.store().destroy(l);
486  m_state.store().set_height(0);
487  return;
488  }
489  augment_path(l);
490  return;
491  }
492 
493  // Steal or merge
494  if (remove_fixup_round(l, path.back())) {
495  augment_path(path);
496  return;
497  }
498 
499  // If l is now the only child of the root, make l the root
500  if (path.size() == 1) {
501  if (m_state.store().count(path.back()) == 1) {
502  l = m_state.store().get_child_leaf(path.back(), 0);
503  m_state.store().set_count(path.back(), 0);
504  m_state.store().destroy(path.back());
505  m_state.store().set_height(1);
506  m_state.store().set_root(l);
507  augment_path(l);
508  return;
509  }
510  augment_path(path);
511  return;
512  }
513 
514  while (true) {
515  // We need to handle the parent
516  internal_type p = path.back();
517  path.pop_back();
518  if (remove_fixup_round(p, path.back())) {
519  augment_path(path);
520  return;
521  }
522 
523  if (path.size() == 1) {
524  if (m_state.store().count(path.back()) == 1) {
525  p = m_state.store().get_child_internal(path.back(), 0);
526  m_state.store().set_count(path.back(), 0);
527  m_state.store().destroy(path.back());
528  m_state.store().set_height(m_state.store().height()-1);
529  m_state.store().set_root(p);
530  path.clear();
531  path.push_back(p);
532  augment_path(path);
533  return;
534  }
535  augment_path(path);
536  return;
537  }
538  }
539  }
540 
544  template <typename X=enab>
545  size_type erase(key_type v, enable<X, !is_static && is_ordered> =enab()) {
546  size_type count = 0;
547  iterator i = find(v);
548  while(i != end()) {
549  erase(i);
550  ++count;
551  i = find(v);
552  }
553 
554  return count;
555  }
556 
561  node_type root() const {
562  if (m_state.store().height() == 1) return node_type(&m_state, m_state.store().get_root_leaf());
563  return node_type(&m_state, m_state.store().get_root_internal());
564  }
565 
569  size_type size() const throw() {
570  return m_state.store().size();
571  }
572 
576  bool empty() const throw() {
577  return m_state.store().size() == 0;
578  }
579 
580  void set_metadata(const std::string & data) {
581  m_state.store().set_metadata(data);
582  }
583 
584  std::string get_metadata() {
585  return m_state.store().get_metadata();
586  }
587 
591  template <typename X=enab>
592  explicit tree(std::string path, comp_type comp=comp_type(), augmenter_type augmenter=augmenter_type(), enable<X, !is_internal> =enab() ):
593  m_state(store_type(path), std::move(augmenter), keyextract_type()),
594  m_comp(comp) {}
595 
599  template <typename X=enab>
600  explicit tree(comp_type comp=comp_type(),
601  augmenter_type augmenter=augmenter_type(),
603  enable<X, is_internal> =enab() ):
604  m_state(store_type(bucket), std::move(augmenter), keyextract_type()),
605  m_comp(comp) {}
606 
607  friend class bbits::builder<T, O>;
608 
609  const comp_type & comp() const {
610  return m_comp;
611  }
612 
613 private:
614  explicit tree(state_type state, comp_type comp):
615  m_state(std::move(state)),
616  m_comp(comp) {}
617 
618  state_type m_state;
619  comp_type m_comp;
620 };
621 
622 } //namespace bbits
623 
624 template <typename T, typename ... Opts>
625 using btree = bbits::tree<T, typename bbits::OptComp<Opts...>::type>;
626 
627 } //namespace tpie
628 #endif /*_TPIE_BTREE_TREE_H_*/
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:592
btree_node< state_type > node_type
Type of node wrapper.
Definition: btree.h:70
Memory management subsystem.
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:431
void insert(value_type v, enable< X,!is_static >=enab())
Insert given value into the btree.
Definition: btree.h:285
state_type::key_type key_type
The type of key used.
Definition: btree.h:60
iterator find(K v, enable< X, is_ordered >=enab()) const
Return an iterator to the first item with the given key.
Definition: btree.h:374
This file contains a few deprecated definitions for legacy code.
size_type erase(key_type v, enable< X,!is_static &&is_ordered >=enab())
remove all items with given key
Definition: btree.h:545
Class storring a reference to a memory bucket.
Definition: memory.h:366
size_type size() const
Return the number of elements in the tree.
Definition: btree.h:569
Augmented btree builder.
Definition: base.h:205
iterator begin() const
Returns an iterator pointing to the beginning of the tree.
Definition: btree.h:266
void erase(const iterator &itr, enable< X,!is_static >=enab())
remove item at iterator
Definition: btree.h:456
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:405
Type that is useful for navigating a btree.
Definition: base.h:178
#define tp_assert(condition, message)
Definition: tpie_assert.h:48
bool empty() const
Check if the tree is empty.
Definition: btree.h:576
store_type::size_type size_type
Type of the size.
Definition: btree.h:75
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:600
state_type::value_type value_type
Type of value stored.
Definition: btree.h:51
node_type root() const
Return the root node.
Definition: btree.h:561
btree_iterator< state_type > iterator
Iterator type.
Definition: btree.h:80
iterator end() const
Returns an iterator pointing to the end of the tree.
Definition: btree.h:275