orbtree
orbtree_node.h
1 /* -*- C++ -*-
2  * orbtree_node.h -- generalized order statistic red-black tree implementation
3  * tree nodes and node allocators
4  *
5  * Copyright 2019 Daniel Kondor <kondor.dani@gmail.com>
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are
9  * met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above
14  * copyright notice, this list of conditions and the following disclaimer
15  * in the documentation and/or other materials provided with the
16  * distribution.
17  * * Neither the name of the nor the names of its
18  * contributors may be used to endorse or promote products derived from
19  * this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  *
33  *
34  */
35 
36 #ifndef ORBTREE_NODE_H
37 #define ORBTREE_NODE_H
38 
39 #include <functional>
40 #include <stdexcept>
41 #include <type_traits>
42 #include <limits>
43 #include <utility>
44 #include <algorithm>
45 
46 
47 //~ #ifdef USE_STACKED_VECTOR
48 #include "vector_stacked.h"
49 //~ template <class T> using compact_vector = stacked_vector::vector<T>;
50 //~ #else
51 #include "vector_realloc.h"
52 //~ template <class T> using compact_vector = realloc_vector::vector<T>;
53 //~ #endif
54 
55 /* constexpr if support only for c++17 or newer */
56 #if __cplusplus >= 201703L
57 #define CONSTEXPR constexpr
58 #else
59 #define CONSTEXPR
60 #endif
61 
62 
63 namespace orbtree {
64 
66  template<class T1, class T2>
67  struct trivial_pair {
68  T1 first;
69  T2 second;
70  trivial_pair() = default;
71  trivial_pair(const T1& x, const T2& y):first(x),second(y) { }
72  trivial_pair(const T1& x, T2&& y):first(x),second(std::move(y)) { }
73  trivial_pair(T1&& x, const T2& y):first(std::move(x)),second(y) { }
74  trivial_pair(T1&& x, T2&& y):first(std::move(x)),second(std::move(y)) { }
75  trivial_pair(const std::pair<T1,T2>& p):first(p.first),second(p.second) { }
76  operator std::pair<T1,T2>() const { return std::pair<T1,T2>(first,second); }
77  operator trivial_pair<const T1,T2>() const { return trivial_pair<const T1,T2>(first,second); }
78  };
79 
80  /* key and optionally value classes */
82  template<class Key> struct KeyOnly {
83  protected:
84  Key k;
85  public:
86  typedef Key KeyType;
87  typedef const Key ValueType;
88 
89  explicit KeyOnly(const Key& k_):k(k_) { }
90  explicit KeyOnly(Key&& k_):k(std::move(k_)) { }
91  template<class... T> explicit KeyOnly(T&&... args) : k(std::forward<T...>(args...)) { }
92  KeyOnly():k() { }
94  const Key& key() const { return k; }
95 
96  ValueType& keyvalue() const { return k; }
99  static const Key& key(const ValueType& k) { return k; }
100 
101  static const bool keyonly = true;
103  void swap(KeyOnly& k_) {
104  using std::swap;
105  swap(k,k_.k);
106  }
107  };
109  template<class Key, class Value, template<class,class> class pair_type = trivial_pair> struct KeyValue {
110  protected:
111  pair_type<Key, Value> p;
112  public:
113  typedef Key KeyType;
114  typedef Value MappedType;
115  /* note: key is not const to make things simpler -- all accessor functions return const ValueType */
116  typedef pair_type<Key, Value> ValueType;
117 
118  explicit KeyValue(const std::pair<Key,Value>& kv):p(kv) { }
119  explicit KeyValue(pair_type<Key,Value>&& kv):p(std::move(kv)) { }
120  explicit KeyValue(const pair_type<Key,Value>& kv):p(kv) { }
121  KeyValue():p() { }
123  const Key& key() const { return p.first; }
125  Value& value() { return p.second; }
127  const Value& value() const { return p.second; }
128 
129  ValueType& keyvalue() { return p; }
130  const ValueType& keyvalue() const { return p; }
133  static const Key& key(const ValueType& kv) { return kv.first; }
134 
135  static const bool keyonly = false;
137  void swap(KeyValue& k_) {
138  using std::swap;
139  swap(p,k_.p);
140  }
141  };
142 
143  template<class Key>
144  void swap(KeyOnly<Key>& x, KeyOnly<Key>& y) {
145  x.swap(y);
146  }
147  template<class Key,class Value>
148  void swap(KeyValue<Key,Value>& x, KeyValue<Key,Value>& y) {
149  x.swap(y);
150  }
151 
152 
153 
154 
161  template<class KeyValueT, class NVTypeT, bool simple = false>
163  protected: /* everything is protected, red-black tree class inherits from this */
164 
165  typedef KeyValueT KeyValue;
166  typedef NVTypeT NVType;
167 
172  struct Node {
173  protected:
174  KeyValue kv;
175  typename std::conditional<simple, NVType, NVType*>::type partialsum;
177  Node* parent;
178  Node* left;
179  Node* right;
180  bool red;
181 
182  public:
183  /* node functionality */
184  Node(const KeyValue& kv_) : kv(kv_), partialsum(0) { }
185  Node(KeyValue&& kv_) : kv(std::move(kv_)), partialsum(0) { }
186  Node():kv(), partialsum(0) { }
187  template<class... T> Node(T&&... args) : kv(std::forward<T...>(args...)), partialsum(0) { }
188  /* note: destructor only deletes the partial sum, does not recursively delete the children */
189  template<bool simple_ = simple> void do_delete(typename std::enable_if<simple_,void*>::type = 0) { }
190  template<bool simple_ = simple> void do_delete(typename std::enable_if<!simple_,void*>::type = 0) {
191  if(partialsum) delete[]partialsum;
192  }
193  ~Node() { do_delete(); }
194 
195  KeyValue& get_key_value() { return kv; }
196  const KeyValue& get_key_value() const { return kv; }
197 
198  bool is_red() const { return red; }
199  bool is_black() const { return !red; }
200  void set_red() { red = true; }
201  void set_black() { red = false; }
202 
203  /* get / set for parent, left and right -- node is considered opaque
204  * by the tree to allow different optimizations here */
205  const Node* get_parent() const { return parent; }
206  const Node* get_left() const { return left; }
207  const Node* get_right() const { return right; }
208  void set_parent(const Node* p) { parent = const_cast<Node*>(p); }
209  void set_left(const Node* x) { left = const_cast<Node*>(x); }
210  void set_right(const Node* x) { right = const_cast<Node*>(x); }
211 
212  friend class NodeAllocatorPtr<KeyValueT,NVTypeT,simple>;
213  };
214 
220  typedef const Node* NodeHandle;
221 
225 
227  const unsigned int nv_per_node;
228  unsigned int get_nv_per_node() const { return nv_per_node; }
229 
230  NodeAllocatorPtr():root(0),nil(0),nv_per_node(1) {
231  root = new_node();
232  nil = new_node();
233  }
234  explicit NodeAllocatorPtr(unsigned int nv_per_node_):root(0),nil(0),nv_per_node(nv_per_node_) {
235  if CONSTEXPR (simple) if(nv_per_node != 1)
236  throw std::runtime_error("For simple tree, weight function can only return one component!\n");
237  root = new_node();
238  nil = new_node();
239  }
240  ~NodeAllocatorPtr() {
241  if(root) free_tree_nodes_r(root);
242  if(nil) delete nil;
243  }
244 
246  Node& get_node(NodeHandle x) { return *const_cast<Node*>(x); }
248  const Node& get_node(const NodeHandle x) const { return *x; }
249 
251  constexpr static Node* Invalid = 0; /* null pointer */
253  const static size_t max_nodes = 0; /* unlimited */
259  Node* new_node() { Node* n = new Node(); init_node(n); return n; }
261  Node* new_node(const KeyValue& kv) { Node* n = new Node(kv); init_node(n); return n; }
263  Node* new_node(KeyValue&& kv) { Node* n = new Node(std::move(kv)); init_node(n); return n; }
265  template<class... T>
266  Node* new_node(T&&... kv) { Node* n = new Node(std::forward<T>(kv)...); init_node(n); return n; }
267 
270  void free_node(NodeHandle n) { delete (Node*)n; }
272  void clear_tree() {
273  if(root) {
274  Node* n = root;
275  if(n->left && n->left != nil) free_tree_nodes_r((Node*)(n->left));
276  if(n->right && n->right != nil) free_tree_nodes_r((Node*)(n->right));
277  n->left = 0;
278  n->right = 0;
279  }
280  }
281 
284  if(n->left && n->left != nil) free_tree_nodes_r((Node*)(n->left));
285  if(n->right && n->right != nil) free_tree_nodes_r((Node*)(n->right));
286  delete n;
287  }
288 
290  template <bool simple_ = simple>
291  void init_node(typename std::enable_if<simple_, Node*>::type n) {
292  if(n) {
293  n->parent = Invalid;
294  n->left = Invalid;
295  n->right = Invalid;
296  }
297  if(!n) throw std::runtime_error("NodeAllocatorPtr::init_node(): out of memory!\n");
298  }
300  template <bool simple_ = simple>
301  void init_node(typename std::enable_if<!simple_, Node*>::type n) {
302  if(n) {
303  n->parent = Invalid;
304  n->left = Invalid;
305  n->right = Invalid;
306  n->partialsum = new NVType[nv_per_node];
307  }
308  if( !n || ! (n->partialsum) ) throw std::runtime_error("NodeAllocatorPtr::init_node(): out of memory!\n");
309  }
310 
312  template<bool simple_ = simple>
313  void get_node_sum(NodeHandle n, typename std::enable_if<simple_,NVType*>::type s) const {
314  *s = n->partialsum;
315  }
317  template<bool simple_ = simple>
318  void get_node_sum(NodeHandle n, typename std::enable_if<!simple_,NVType*>::type s) const {
319  for(unsigned int i = 0; i < nv_per_node; i++) s[i] = n->partialsum[i];
320  }
322  template<bool simple_ = simple>
323  void set_node_sum(NodeHandle n1, typename std::enable_if<simple_,const NVType*>::type s) {
324  Node* n = const_cast<Node*>(n1);
325  n->partialsum = *s;
326  }
328  template<bool simple_ = simple>
329  void set_node_sum(NodeHandle n1, typename std::enable_if<!simple_,const NVType*>::type s) {
330  Node* n = const_cast<Node*>(n1);
331  for(unsigned int i = 0; i < nv_per_node; i++) n->partialsum[i] = s[i];
332  }
333  };
334 
335 
354  template<class KeyValueT, class NVTypeT, class IndexType>
356  protected:
357  //~ static_assert(std::is_trivially_copyable<KeyValueT>::value,
358  //~ "Key and Value must be trivially copyable to use compact flat allocator!\n");
359  typedef IndexType NodeHandle;
360  typedef KeyValueT KeyValue;
361  typedef NVTypeT NVType;
362 
363  private:
364  static constexpr IndexType redbit = 1U << (std::numeric_limits<IndexType>::digits - 1);
365  static constexpr IndexType max_nodes = redbit - 1;
366  static constexpr IndexType deleted_indicator = (max_nodes | redbit); /* 0xFFFFFFFFh */
367 
368  protected:
370  struct Node {
371  protected:
373  KeyValue kv;
375  IndexType parent;
376  IndexType left;
377  IndexType right;
378  /* red-black flag is stored inside parent */
379 
380  public:
381  Node(const KeyValue& kv_) : kv(kv_), parent(NodeAllocatorCompact::Invalid),
382  left(NodeAllocatorCompact::Invalid), right(NodeAllocatorCompact::Invalid) { }
383  Node(KeyValue&& kv_) : kv(kv_), parent(NodeAllocatorCompact::Invalid),
385  template<class... T> Node(T&&... args) : kv(std::forward<T...>(args...)), parent(NodeAllocatorCompact::Invalid),
387  Node():kv(), parent(NodeAllocatorCompact::Invalid),
389 
390  KeyValue& get_key_value() { return kv; }
391  const KeyValue& get_key_value() const { return kv; }
392  bool is_red() const { return parent & NodeAllocatorCompact::redbit; }
393  bool is_black() const { return !is_red(); }
394  void set_red() { parent |= NodeAllocatorCompact::redbit; }
395  void set_black() { parent &= (~NodeAllocatorCompact::redbit); }
396 
397  NodeHandle get_parent() const { return parent & (~NodeAllocatorCompact::redbit); }
398  NodeHandle get_left() const { return left; }
399  NodeHandle get_right() const { return right; }
400  void set_parent(NodeHandle p) {
401  if(p > NodeAllocatorCompact::max_nodes) throw std::runtime_error("NodeAllocatorCompact::Node::set_parent(): parent ID too large!\n");
402  parent = p | (parent & NodeAllocatorCompact::redbit);
403  }
404  void set_left(NodeHandle x) { left = x; }
405  void set_right(NodeHandle x) { right = x; }
406 
408  void set_deleted() { parent = NodeAllocatorCompact::deleted_indicator; }
410  bool is_deleted() const { return (parent == NodeAllocatorCompact::deleted_indicator); }
411 
412  /* swap contents with other node */
413  void swap(Node& n) {
414  using std::swap;
415  swap(kv,n.kv);
416  swap(parent,n.parent);
417  swap(left,n.left);
418  swap(right,n.right);
419  }
420 
421  friend class NodeAllocatorCompact<KeyValueT,NVTypeT,IndexType>;
422  };
423 
424  private:
425 
426 #ifdef USE_STACKED_VECTOR
427  typedef stacked_vector::vector<Node> node_vector_type;
428 #else
429  typedef typename std::conditional< std::is_trivially_copyable<KeyValueT>::value,
431 #endif
432 
434  node_vector_type nodes;
435  const unsigned int nv_per_node;
436  size_t n_del;
437  NodeHandle deleted_nodes_head;
438 
439  protected:
441  static constexpr NodeHandle Invalid = max_nodes;
442  NodeHandle root;
443  NodeHandle nil;
445  NodeAllocatorCompact():nv_per_node(1),n_del(0),deleted_nodes_head(Invalid),root(Invalid),nil(Invalid) {
446  root = new_node();
447  nil = new_node();
448  }
449  explicit NodeAllocatorCompact(unsigned int nv_per_node_):nv_per_node(nv_per_node_),n_del(0),
450  deleted_nodes_head(Invalid),root(Invalid),nil(Invalid) {
451  root = new_node();
452  nil = new_node();
453  }
454  //~ ~NodeAllocatorCompact() { }
455  /* main interface */
457  Node& get_node(NodeHandle x) { return nodes[x]; }
459  const Node& get_node(NodeHandle x) const { return nodes[x]; }
460 
461 
462  private:
464  bool try_get_node(NodeHandle& n) {
465  if(deleted_nodes_head != Invalid) {
466  if(!n_del) throw std::runtime_error("NodeAllocatorCompact::alloc_node(): inconsistent deleted nodes!\n");
467  n_del--;
468  n = deleted_nodes_head;
469  nodes[n].set_parent(Invalid);
470  deleted_nodes_head = nodes[deleted_nodes_head].get_left();
471  if(deleted_nodes_head != Invalid) nodes[deleted_nodes_head].set_right(Invalid);
472  return true;
473  }
474  else return false;
475  }
476 
478  void move_nv(IndexType x, IndexType y) {
479  size_t xbase = ((size_t)x)*nv_per_node;
480  size_t ybase = ((size_t)y)*nv_per_node;
481  for(unsigned int i=0;i<nv_per_node;i++) nvarray[xbase + i] = nvarray[ybase + i];
482  }
483 
489  void move_node(NodeHandle x, NodeHandle y) {
490  nodes[x] = std::move(nodes[y]); /* no need to swap (i.e. preserve values in x) */
491  move_nv(x,y); /* move rank function as well */
492  /* note: destructor is not called for y (memory is not freed) */
493  if(y == root || y == nil) throw std::runtime_error("NodeAllocatorCompact::move_node(): root or nil is moved!\n");
494  /* update parent and children if needed */
495  if(nodes[x].get_parent() != Invalid && nodes[x].get_parent() != nil) {
496  if(nodes[nodes[x].get_parent()].get_left() == y) nodes[nodes[x].get_parent()].set_left(x);
497  else {
498  if(nodes[nodes[x].get_parent()].get_right() == y) nodes[nodes[x].get_parent()].set_right(x);
499  else throw std::runtime_error("NodeAllocatorCompact::move_node(): inconsistent tree detected!\n");
500  }
501  }
502  else throw std::runtime_error("NodeAllocatorCompact::move_node(): node with no parent!\n");
503  if(nodes[x].get_left() != Invalid && nodes[x].get_left() != nil) {
504  if(nodes[nodes[x].get_left()].get_parent() != y)
505  throw std::runtime_error("NodeAllocatorCompact::move_node(): inconsistent tree detected!\n");
506  nodes[nodes[x].get_left()].set_parent(x);
507  }
508  if(nodes[x].get_right() != Invalid && nodes[x].get_right() != nil) {
509  if(nodes[nodes[x].get_right()].get_parent() != y)
510  throw std::runtime_error("NodeAllocatorCompact::move_node(): inconsistent tree detected!\n");
511  nodes[nodes[x].get_right()].set_parent(x);
512  }
513  }
514 
516  void shrink_memory(IndexType new_capacity = 0) {
517  nodes.shrink_to_fit(new_capacity);
518  nvarray.shrink_to_fit(((size_t)new_capacity)*nv_per_node);
519  }
520 
521  protected:
523  NodeHandle new_node() {
524  NodeHandle n = nodes.size();
525  /* use previously deleted node, if available */
526  if(try_get_node(n)) nodes[n] = Node();
527  else {
528  /* create new node */
529  if(n == max_nodes) throw std::runtime_error("NodeAllocatorFlat::new_node(): reached maximum number of nodes!\n");
530  nodes.emplace_back();
531  nvarray.resize(((size_t)(n+1))*nv_per_node,NVType());
532  }
533  return n;
534  }
536  NodeHandle new_node(const KeyValue& kv) {
537  NodeHandle n = nodes.size();
538  if(try_get_node(n)) nodes[n] = Node(kv);
539  else {
540  if(n == max_nodes) throw std::runtime_error("NodeAllocatorFlat::new_node(): reached maximum number of nodes!\n");
541  nodes.emplace_back(kv);
542  nvarray.resize(((size_t)(n+1))*nv_per_node,NVType());
543  }
544  return n;
545  }
547  NodeHandle new_node(KeyValue&& kv) {
548  NodeHandle n = nodes.size();
549  if(try_get_node(n)) nodes[n] = Node(std::forward<KeyValue>(kv));
550  else {
551  if(n == max_nodes) throw std::runtime_error("NodeAllocatorFlat::new_node(): reached maximum number of nodes!\n");
552  nodes.emplace_back(std::forward<KeyValue>(kv));
553  nvarray.resize(((size_t)(n+1))*nv_per_node,NVType());
554  }
555  return n;
556  }
558  template<class... T> NodeHandle new_node(T&&... kv) {
559  NodeHandle n = nodes.size();
560  if(try_get_node(n)) nodes[n] = Node(std::forward<T>(kv)...);
561  else {
562  if(n == max_nodes) throw std::runtime_error("NodeAllocatorFlat::new_node(): reached maximum number of nodes!\n");
563  nodes.emplace_back(std::forward<T>(kv)...);
564  nvarray.resize(((size_t)(n+1))*nv_per_node,NVType());
565  }
566  return n;
567  }
568 
570  void free_node(NodeHandle n) {
571  /* store deleted nodes in a linked list */
572  nodes[n].set_deleted();
573  nodes[n].set_right(Invalid);
574  nodes[n].set_left(deleted_nodes_head);
575  if(deleted_nodes_head != Invalid) nodes[deleted_nodes_head].set_right(n);
576  deleted_nodes_head = n;
577  n_del++;
578  }
580  void clear_tree() {
581  nodes.resize(2);
582  nvarray.resize(2);
583  //~ size = 2;
584  root = 0;
585  nil = 1;
586  nodes[root] = Node();
587  nodes[nil] = Node();
588  shrink_memory(4);
589  }
590 
591 
593  unsigned int get_nv_per_node() const { return nv_per_node; }
594 
596  void get_node_sum(NodeHandle n, NVType* s) const {
597  size_t base = ((size_t)n)*nv_per_node;
598  for(unsigned int i=0;i<nv_per_node;i++) s[i] = nvarray[base+i];
599  }
601  void set_node_sum(NodeHandle n, const NVType* s) {
602  size_t base = ((size_t)n)*nv_per_node;
603  for(unsigned int i=0;i<nv_per_node;i++) nvarray[base+i] = s[i];
604  }
605 
606  public:
607 
609  size_t capacity() const { return nodes.capacity(); }
611  size_t deleted_nodes() const { return n_del; }
612 
614  void shrink_to_fit() {
615  while(deleted_nodes_head != Invalid) {
616  /* remove nodes at the end */
617  NodeHandle size = nodes.size();
618  if(size == 0) throw std::runtime_error("NodeAllocatorCompact::shrink_size(): ran out of nodes!\n");
619  size--;
620  if(nodes[size].is_deleted()) {
621  /* if last node was deleted, update the list of deleted nodes */
622  NodeHandle left = nodes[size].get_left();
623  NodeHandle right = nodes[size].get_right();
624  if(left != Invalid) nodes[left].set_right(right);
625  if(right != Invalid) nodes[right].set_left(left);
626  if(deleted_nodes_head == size) deleted_nodes_head = left;
627  }
628  else {
629  /* otherwise move last node into the place of a deleted node */
630  NodeHandle n = deleted_nodes_head;
631  if(n == size)
632  throw std::runtime_error("NodeAllocatorCompact::shrink_size(): inconsistent deleted nodes!\n");
633  deleted_nodes_head = nodes[deleted_nodes_head].get_left();
634  nodes[deleted_nodes_head].set_right(Invalid);
635  move_node(n,size);
636  }
637  nodes.pop_back();
638  nvarray.resize(((size_t)size)*nv_per_node);
639  if(!n_del) throw std::runtime_error("NodeAllocatorCompact::shrink_size(): inconsistent deleted nodes!\n");
640  n_del--;
641  }
642  shrink_memory();
643  }
644 
647  void reserve(size_t size) {
648  nvarray.reserve(size);
649  nodes.reserve(size);
650  }
651  };
652 }
653 
654 
655 
656 #endif
657 
static const Key & key(const ValueType &k)
helper to extract the key from ValueType – contrast it with KeyValue
Definition: orbtree_node.h:99
KeyValue kv
key and (optionally) value stored
Definition: orbtree_node.h:174
const Node * NodeHandle
Node handle type to be used by tree implementation.
Definition: orbtree_node.h:220
Node & get_node(NodeHandle x)
get reference to a modifiable node
Definition: orbtree_node.h:246
void init_node(typename std::enable_if<!simple_, Node *>::type n)
safely initialize new node, throw an exception if memory allocation failed
Definition: orbtree_node.h:301
const ValueType & keyvalue() const
universal access to key / key-value pair
Definition: orbtree_node.h:130
void clear_tree()
clear tree, to be reused
Definition: orbtree_node.h:580
const Node * get_left() const
get handle for left child
Definition: orbtree_node.h:206
void free_node(NodeHandle n)
delete node – tree is not traversed, the caller must arrange to "cut" out the node in question (othe...
Definition: orbtree_node.h:270
void init_node(typename std::enable_if< simple_, Node *>::type n)
safely initialize new node, throw an exception if memory allocation failed
Definition: orbtree_node.h:291
const Key & key() const
access key value – only const access is possible, key should not change
Definition: orbtree_node.h:94
Node * new_node()
get new node
Definition: orbtree_node.h:259
trivially copyable pair, similar to std::pair
Definition: orbtree_node.h:67
void get_node_sum(NodeHandle n, typename std::enable_if<!simple_, NVType *>::type s) const
get the value of the partial sum of weights stored in this node – case when the weight function retu...
Definition: orbtree_node.h:318
wrapper class for a key-value pair
Definition: orbtree_node.h:109
NodeHandle new_node(KeyValue &&kv)
get new node – note that it is the callers responsibility to store the handle in the tree ...
Definition: orbtree_node.h:547
void clear_tree()
clear tree, i.e. free all nodes, but keep root (sentinel) and nil, so that tree can be used again ...
Definition: orbtree_node.h:272
pair_type< Key, Value > p
key and value, key should not change – not const to allow swapping / moving nodes ...
Definition: orbtree_node.h:111
void shrink_to_fit(size_t new_capacity=0)
Free up unused memory.
Definition: vector_realloc.h:423
Node * new_node(T &&... kv)
get new node
Definition: orbtree_node.h:266
const Node * get_parent() const
get handle for parent
Definition: orbtree_node.h:205
Node * new_node(KeyValue &&kv)
get new node
Definition: orbtree_node.h:263
bool is_red() const
test if this node is red
Definition: orbtree_node.h:198
void set_red()
set this node red
Definition: orbtree_node.h:200
unsigned int get_nv_per_node() const
each node has nv_per_node values calculated and stored in it
Definition: orbtree_node.h:593
void reserve(size_t n)
Reserve memory for at least n elements. Throws an exception if memory allocation is not successful...
Definition: vector_realloc.h:242
IndexType right
Right child.
Definition: orbtree_node.h:377
const Node * get_right() const
get handle for right child
Definition: orbtree_node.h:207
NodeAllocatorCompact()
Nil sentinel.
Definition: orbtree_node.h:445
Alternate node allocator with the aim to use less memory.
Definition: orbtree_node.h:355
bool is_black() const
test if this node is black
Definition: orbtree_node.h:199
Node & get_node(NodeHandle x)
get reference to a modifiable node
Definition: orbtree_node.h:457
NodeHandle nil
Root sentinel.
Definition: orbtree_node.h:443
wrapper class for key that can go in sets and multisets
Definition: orbtree_node.h:82
ValueType & keyvalue()
universal access to key / key-value pair
Definition: orbtree_node.h:129
ValueType & keyvalue() const
universal access to key / key-value pair
Definition: orbtree_node.h:96
void set_parent(const Node *p)
set handle for parent
Definition: orbtree_node.h:208
static const Key & key(const ValueType &kv)
helper to extract only the key from ValueType
Definition: orbtree_node.h:133
Node * new_node(const KeyValue &kv)
get new node
Definition: orbtree_node.h:261
Basic allocator that allocates each node individually, using C++ new / delete and pointers...
Definition: orbtree_node.h:162
const Key & key() const
access key – only const access is possible, key should not change
Definition: orbtree_node.h:123
void set_deleted()
Set a flag indicating this node has been deleted (but memory has not been freed yet).
Definition: orbtree_node.h:408
node class
Definition: orbtree_node.h:172
Key k
actual key; should not change during a node&#39;s lifetime – not const to allow swapping / moving nodes ...
Definition: orbtree_node.h:84
const Node & get_node(const NodeHandle x) const
get reference to a const node
Definition: orbtree_node.h:248
Definition: orbtree.h:55
size_t capacity() const
get the current capacity of the underlying storage
Definition: orbtree_node.h:609
void reserve(size_t size)
Reserve storage for at least the requested number of elements. It can throw an exception on failure t...
Definition: orbtree_node.h:647
void shrink_to_fit()
Free up memory taken up by deleted nodes by rearranging storage.
Definition: orbtree_node.h:614
void set_black()
set this node black
Definition: orbtree_node.h:201
static constexpr NodeHandle Invalid
invalid handle
Definition: orbtree_node.h:441
KeyValue kv
Key and (optionally) value stored in this node.
Definition: orbtree_node.h:373
const unsigned int nv_per_node
each node has nv_per_node values calculated and stored in it
Definition: orbtree_node.h:227
void free_tree_nodes_r(Node *n)
free whole tree (starting from root)
Definition: orbtree_node.h:283
void free_node(NodeHandle n)
delete node – tree is not traversed, the caller must arrange to "cut" out the node in question ...
Definition: orbtree_node.h:570
bool is_deleted() const
Check if this node is deleted.
Definition: orbtree_node.h:410
C++ vector-like container that internally maintains a "stack" of vectors instead of having one large ...
Definition: vector_stacked.h:171
const Node & get_node(NodeHandle x) const
get reference to a const node
Definition: orbtree_node.h:459
void set_node_sum(NodeHandle n, const NVType *s)
set the partial sum stored in node n
Definition: orbtree_node.h:601
C++ vector-like container for trivially moveable types, using realloc() for growing memory...
Definition: vector_realloc.h:115
NodeHandle new_node(const KeyValue &kv)
get new node – note that it is the callers responsibility to store the handle in the tree ...
Definition: orbtree_node.h:536
NodeHandle new_node(T &&... kv)
get new node – note that it is the callers responsibility to store the handle in the tree ...
Definition: orbtree_node.h:558
std::conditional< simple, NVType, NVType * >::type partialsum
partial sum (sum of this node&#39;s children&#39;s weight + this node&#39;s weight)
Definition: orbtree_node.h:176
IndexType left
Left child.
Definition: orbtree_node.h:376
Value & value()
access value
Definition: orbtree_node.h:125
const Value & value() const
access value
Definition: orbtree_node.h:127
IndexType parent
Parent node reference, actually an index in a vector; also stores red-black flag. ...
Definition: orbtree_node.h:375
size_t deleted_nodes() const
get the number of deleted nodes
Definition: orbtree_node.h:611
void set_left(const Node *x)
set handle for left child
Definition: orbtree_node.h:209
void get_node_sum(NodeHandle n, typename std::enable_if< simple_, NVType *>::type s) const
get the value of the partial sum of weights stored in this node – simple case when the weight functi...
Definition: orbtree_node.h:313
void resize(size_t count)
Resize vector. If new size is larger than current size, new elements are default constructed. Can throw an exception on memory allocation error.
Definition: vector_realloc.h:278
void set_right(const Node *x)
set handle for right child
Definition: orbtree_node.h:210
Node * nil
Sentinel for nil.
Definition: orbtree_node.h:224
Node * root
Root sentinel, allocated automatically, used when freeing the tree.
Definition: orbtree_node.h:223
void set_node_sum(NodeHandle n1, typename std::enable_if< simple_, const NVType *>::type s)
set the value of the partial sum stored in this node – simple case when the weight function returns ...
Definition: orbtree_node.h:323
Node object.
Definition: orbtree_node.h:370
NodeHandle new_node()
get new node – note that it is the callers responsibility to store the handle in the tree ...
Definition: orbtree_node.h:523
void set_node_sum(NodeHandle n1, typename std::enable_if<!simple_, const NVType *>::type s)
set the value of the partial sum stored in this node – case when the weight function returns a vecto...
Definition: orbtree_node.h:329
void get_node_sum(NodeHandle n, NVType *s) const
get the partial sum stored in node n
Definition: orbtree_node.h:596