Yggdrasill  0.2
bst.hpp
1 #ifndef YGG_BST_HPP
2 #define YGG_BST_HPP
3 
4 #include "options.hpp"
5 #include "size_holder.hpp"
6 #include "tree_iterator.hpp"
7 #include "util.hpp"
8 
9 #include <cassert>
10 #include <cstddef>
11 #include <set>
12 #include <type_traits>
13 
14 #ifdef YGG_STORE_SEQUENCE
15 #include "benchmark_sequence.hpp"
16 #endif
17 
18 // Only for debugging purposes
19 #include <fstream>
20 #include <vector>
21 
22 namespace ygg {
23 namespace bst {
24 
25 #ifdef YGG_STORE_SEQUENCE
26 class DummySequenceInterface {
27 public:
28  using KeyT = bool; // Set this to whatever your nodes use as key. Anything
29  // non-numeric will probably blow up
30  static KeyT
31  get_key(/* Your node class */) = delete; // You must implement this!
32 };
33 #endif
34 
35 template <class Node>
37 public:
38  Node * get_parent() const noexcept;
39  Node *& get_parent() noexcept;
40  void set_parent(Node * parent) noexcept;
41  static constexpr bool parent_reference = true;
42 
43 private:
44  Node * _bst_parent;
45 };
46 
47 // TODO document
48 template <class Node>
50 public:
51  void
52  init_root(Node * root) const noexcept
53  {
54  (void)root;
55  };
56  void
57  descend_left(Node * child) const noexcept
58  {
59  (void)child;
60  };
61  void
62  descend_right(Node * child) const noexcept
63  {
64  (void)child;
65  };
66  void
67  found(Node * node) const noexcept
68  {
69  (void)node;
70  };
71  void not_found() const noexcept {};
72 
73  static DefaultFindCallbacks<Node> dummy;
74 };
75 
76 template <class Node, class Tag = int,
77  class ParentContainer = DefaultParentContainer<Node>>
78 class BSTNodeBase {
79 
80 private:
81  /* Determine whether our parent storage allows us to obtain a
82  * reference to the parent pointer. Used for set-by-arithmetic magic. */
83  constexpr static auto
84  compute_parent_pointer_type()
85  {
86  if constexpr (ParentContainer::parent_reference) {
87  return utilities::TypeHolder<Node *&>{};
88  } else {
89  return utilities::TypeHolder<Node *>{};
90  }
91  }
92 
93 protected:
94  Node * _bst_children[2];
95  ParentContainer _bst_parent;
96 
97  template <class InnerNode>
98  friend InnerNode * utilities::go_right_if(bool cond, InnerNode * parent);
99  template <class InnerNode>
100  friend InnerNode * utilities::go_left_if(bool cond, InnerNode * parent);
101 
102 public:
103  void set_parent(Node * new_parent) noexcept;
104  Node * get_parent() const noexcept;
105  template <class InnerPC = ParentContainer>
106  std::enable_if_t<InnerPC::parent_reference, Node *&> get_parent() const
107  noexcept;
108 
109  void set_left(Node * new_left) noexcept;
110  void set_right(Node * new_right) noexcept;
111  Node *& get_left() noexcept;
112  Node *& get_right() noexcept;
113  Node * const & get_left() const noexcept;
114  Node * const & get_right() const noexcept;
115 
116  // Debugging methods TODO remove this
117  size_t get_depth() const noexcept;
118 };
119 
120 template <class Node, class Options, class Tag = int,
121  class Compare = ygg::utilities::flexible_less,
122  class ParentContainer = DefaultParentContainer<Node>>
124 public:
125  using MyClass =
127  // Node Base
129  static_assert(std::is_base_of<NB, Node>::value,
130  "Node class not properly derived from BSTNodeBase");
131 
135  BinarySearchTree() noexcept;
136 
145  BinarySearchTree(MyClass && other) noexcept;
146 
155  MyClass & operator=(MyClass && other) noexcept;
156 
157  /******************************************************
158  ******************************************************
159  * Begin of iterator declaration
160  ******************************************************
161  ******************************************************/
162 private:
163  // Class to tell the abstract search tree iterator how to handle our nodes
164  class NodeInterface {
165  public:
166  static Node *
167  get_parent(Node * n) noexcept
168  {
169  return n->NB::get_parent();
170  }
171  static Node *
172  get_left(Node * n) noexcept
173  {
174  return n->NB::get_left();
175  }
176  static Node *
177  get_right(Node * n) noexcept
178  {
179  return n->NB::get_right();
180  }
181 
182  static const Node *
183  get_parent(const Node * n) noexcept
184  {
185  return n->NB::get_parent();
186  }
187  static const Node *
188  get_left(const Node * n) noexcept
189  {
190  return n->NB::get_left();
191  }
192  static const Node *
193  get_right(const Node * n) noexcept
194  {
195  return n->NB::get_right();
196  }
197  };
198 
199 public:
200  // forward, for friendship
201  template <bool reverse>
203 
204  template <bool reverse>
205  class iterator : public internal::IteratorBase<iterator<reverse>, Node,
206  NodeInterface, reverse> {
207  public:
208  using internal::IteratorBase<iterator<reverse>, Node, NodeInterface,
209  reverse>::IteratorBase;
210  iterator(const iterator<reverse> & orig) noexcept
211  : internal::IteratorBase<iterator<reverse>, Node, NodeInterface,
212  reverse>(orig.n){};
213  iterator() noexcept
214  : internal::IteratorBase<iterator<reverse>, Node, NodeInterface,
215  reverse>(){};
216 
218  operator=(const iterator<reverse> & orig) noexcept = default;
219 
220  private:
221  friend class const_iterator<reverse>;
222  };
223 
224  template <bool reverse>
225  class const_iterator
226  : public internal::IteratorBase<const_iterator<reverse>, const Node,
227  NodeInterface, reverse> {
228  public:
229  using internal::IteratorBase<const_iterator<reverse>, const Node,
230  NodeInterface, reverse>::IteratorBase;
231  const_iterator(const const_iterator<reverse> & orig) noexcept
232  : internal::IteratorBase<const_iterator<reverse>, const Node,
233  NodeInterface, reverse>(orig.n){};
234  const_iterator(const iterator<reverse> & orig) noexcept
235  : internal::IteratorBase<const_iterator<reverse>, const Node,
236  NodeInterface, reverse>(orig.n){};
237  const_iterator() noexcept
238  : internal::IteratorBase<const_iterator<reverse>, const Node,
239  NodeInterface, reverse>(){};
240 
242  operator=(const const_iterator<reverse> & orig) noexcept = default;
243  };
244 
245  /******************************************************
246  ******************************************************
247  * End of iterator declaration
248  ******************************************************
249  ******************************************************/
250 
251 protected:
252  // TODO document
253  inline Node * get_first_equal(Node * n) noexcept;
254 
255 public:
256  // TODO document ensure_firstx
277  template <class Comparable, bool ensure_first = false>
278  const_iterator<false> find(const Comparable & query) const
279  CMP_NOEXCEPT(query);
280  template <class Comparable, bool ensure_first = false>
281  iterator<false> find(const Comparable & query) CMP_NOEXCEPT(query);
282 
283  // TODO document
284  // TODO test
285  // TODO noexcept-expression?
286  template <class Comparable, class Callbacks = DefaultFindCallbacks<Node>>
287  iterator<false> find(const Comparable & query, Callbacks * cbs);
288 
311  template <class Comparable>
312  const_iterator<false> upper_bound(const Comparable & query) const
313  CMP_NOEXCEPT(query);
314  template <class Comparable>
315  iterator<false> upper_bound(const Comparable & query) CMP_NOEXCEPT(query);
316 
338  template <class Comparable>
339  const_iterator<false> lower_bound(const Comparable & query) const
340  CMP_NOEXCEPT(query);
341  template <class Comparable>
342  iterator<false> lower_bound(const Comparable & query) CMP_NOEXCEPT(query);
343 
352  template <class NodeTraits>
353  void dump_to_dot(const std::string & filename) const;
354 
355  // Iteration
359  const_iterator<false> cbegin() const noexcept;
363  const_iterator<false> cend() const noexcept;
367  const_iterator<false> begin() const noexcept;
368  iterator<false> begin() noexcept;
369 
373  const_iterator<false> end() const noexcept;
374  iterator<false> end() noexcept;
375 
379  const_iterator<true> crbegin() const noexcept;
384  const_iterator<true> crend() const noexcept;
388  const_iterator<true> rbegin() const noexcept;
389  iterator<true> rbegin() noexcept;
390 
395  const_iterator<true> rend() const noexcept;
396  iterator<true> rend() noexcept;
397 
403  const_iterator<false> iterator_to(const Node & node) const noexcept;
404  iterator<false> iterator_to(Node & node) noexcept;
405 
416  size_t size() const noexcept;
417 
423  void clear() noexcept;
424 
432  bool empty() const noexcept;
433 
434  // TODO document
435  // TODO do we need them anymore?
436  Node * get_root() const noexcept;
437  static Node * get_parent(Node * n) noexcept;
438  static Node * get_left_child(Node * n) noexcept;
439  static Node * get_right_child(Node * n) noexcept;
440 
441  // Mainly debugging methods
443  bool verify_integrity() const;
444  void dbg_verify() const;
445  void dbg_print_tree() const;
447 
448 protected:
449  Node * root;
450 
451  Node * get_smallest() const noexcept;
452  Node * get_largest() const noexcept;
453  Node * get_uncle(Node * node) const noexcept;
454 
455  Compare cmp;
456 
457  SizeHolder<Options::constant_time_size> s;
458 
459  /* What follows are debugging tools */
460  template <class NodeNameGetter>
461  void dump_to_dot_base(const std::string & filename,
462  NodeNameGetter name_getter) const;
463 
464  template <class NodeNameGetter>
465  void output_node_base(const Node * node, std::ofstream & out,
466  NodeNameGetter name_getter) const;
467 
468  // @cond INTERNAL
469  void verify_tree() const;
470  void verify_order() const;
471  void verify_size() const;
472  // @endcond
473 
474 #ifdef YGG_STORE_SEQUENCE
475  typename ygg::utilities::template BenchmarkSequenceStorage<
476  typename Options::SequenceInterface::KeyT>
477  bss;
478 #endif
479 };
480 
481 } // namespace bst
482 } // namespace ygg
483 
484 #ifndef YGG_BST_CPP
485 #include "bst.cpp"
486 #endif
487 
488 #endif // YGG_BST_HPP
Definition: bst.hpp:123
Definition: bst.hpp:78
Definition: bst.hpp:49
Definition: bst.hpp:36
Definition: rbtree.hpp:18