Aleph-w  1.9
General library for algorithms and data structures
tpl_rand_tree.H
1 
2 /* Aleph-w
3 
4  / \ | | ___ _ __ | |__ __ __
5  / _ \ | |/ _ \ '_ \| '_ \ ____\ \ /\ / / Data structures & Algorithms
6  / ___ \| | __/ |_) | | | |_____\ V V / version 1.9b
7  /_/ \_\_|\___| .__/|_| |_| \_/\_/ https://github.com/lrleon/Aleph-w
8  |_|
9 
10  This file is part of Aleph-w library
11 
12  Copyright (c) 2002-2018 Leandro Rabindranath Leon & Alejandro Mujica
13 
14  This program is free software: you can redistribute it and/or modify
15  it under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  This program is distributed in the hope that it will be useful, but
20  WITHOUT ANY WARRANTY; without even the implied warranty of
21  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22  General Public License for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with this program. If not, see <https://www.gnu.org/licenses/>.
26 */
27 
28 # ifndef TPL_RAND_TREE_H
29 # define TPL_RAND_TREE_H
30 
31 # include <limits.h>
32 # include <gsl/gsl_rng.h>
33 # include <ahUtils.H>
34 # include <ahFunction.H>
35 # include <tpl_randNode.H>
36 # include <tpl_binTreeOps.H>
37 
38 using namespace Aleph;
39 
40 namespace Aleph {
41 
70  template <template <typename> class NodeType, typename Key, class Compare>
72 {
73 public:
74 
75  using Node = NodeType<Key>;
76 
77 private:
78 
79  Node * tree_root;
80  gsl_rng * r;
81  Compare cmp;
82 
83  Node * random_insert(Node * root, Node * p) noexcept
84  {
85  const long & n = COUNT(root);
86  const size_t rn = gsl_rng_uniform_int(r, n + 1);
87  if (rn == n) // p wins the raffle?
89 
90  Node * result;
91  if (cmp(KEY(p), KEY(root))) // KEY(p) < KEY(root) ?
92  {
93  result = random_insert(LLINK(root), p);
94  if (result != Node::NullPtr) // p was inserted?
95  {
96  LLINK(root) = result;
97  ++COUNT(root);
98  return root;
99  }
100  }
101  else if (cmp(KEY(root), KEY(p))) // KEY(p) > KEY(root) ?
102  {
103  result = random_insert(RLINK(root), p);
104  if (result != Node::NullPtr) // p was inserted?
105  {
106  RLINK(root) = result;
107  ++COUNT(root);
108  return root;
109  }
110  }
111 
112  return Node::NullPtr; // duplicated key ==> no insertion
113  }
114 
115  Node * random_insert_dup(Node * root, Node * p) noexcept
116  {
117  const long & n = COUNT(root);
118  const size_t rn = gsl_rng_uniform_int(r, n + 1);
119  if (rn == n) // p wins the raffle?
121 
122  if (cmp(KEY(p), KEY(root))) // KEY(p) < KEY(root) ?
123  LLINK(root) = random_insert_dup(LLINK(root), p);
124  else
125  RLINK(root) = random_insert_dup(RLINK(root), p);
126 
127  ++COUNT(root);
128 
129  return root;
130  }
131 
132  Gen_Rand_Tree& operator = (const Gen_Rand_Tree&);
133 
134  void init(unsigned long seed)
135  {
136  r = gsl_rng_alloc (gsl_rng_mt19937);
137 
138  if (r == nullptr)
139  throw std::bad_alloc();
140 
141  gsl_rng_set(r, seed % gsl_rng_max(r));
142  }
143 
144 public:
145 
147  Compare & key_comp() noexcept { return cmp; }
148 
150  Compare & get_compare() noexcept { return key_comp(); }
151 
153  gsl_rng * gsl_rng_object() noexcept { return r;}
154 
156  void set_seed(unsigned long seed) noexcept { gsl_rng_set(r, seed); }
157 
160  Gen_Rand_Tree(unsigned int seed, Compare __cmp = Compare()) noexcept
161  : tree_root(Node::NullPtr), r(nullptr), cmp(__cmp)
162  {
163  init(seed);
164  }
165 
168  Gen_Rand_Tree(Compare cmp = Compare()) noexcept
169  : Gen_Rand_Tree(time(nullptr), cmp) { /* empty */ }
170 
172  void swap(Gen_Rand_Tree & tree) noexcept
173  {
174  std::swap(tree_root, tree.tree_root);
175  std::swap(r, tree.r);
176  std::swap(cmp, tree.cmp);
177  }
178 
179  virtual ~Gen_Rand_Tree() noexcept
180  {
181  if (r != nullptr)
182  gsl_rng_free(r);
183  }
184 
191  Node * insert(Node * p) noexcept
192  {
193  assert(p != Node::NullPtr);
194  assert((LLINK(p) == Node::NullPtr) and (RLINK(p) == Node::NullPtr));
195  assert(COUNT(p) == 1);
196 
197  Node * result = random_insert(tree_root, p);
198  if (result == Node::NullPtr)
199  return nullptr;
200 
201  return tree_root = result;
202  }
203 
211  Node * insert_dup(Node * p) noexcept
212  {
213  assert(p != Node::NullPtr);
214  assert((LLINK(p) == Node::NullPtr) and (RLINK(p) == Node::NullPtr));
215  assert(COUNT(p) == 1);
216 
217  return tree_root = random_insert_dup(tree_root, p);
218  }
219 
220 private:
221 
222  Node * random_join_exclusive(Node * tl, Node * tr) noexcept
223  {
224  if (tl == Node::NullPtr)
225  return tr;
226 
227  if (tr == Node::NullPtr)
228  return tl;
229 
230  const size_t & m = COUNT(tl);
231  const size_t & n = COUNT(tr);
232  const size_t rn = 1 + gsl_rng_uniform_int(r, m + n);
233  if (rn <= m)
234  { // left subtree wins
235  COUNT(tl) += COUNT(tr);
236  RLINK(tl) = random_join_exclusive(RLINK(tl), tr);
237  return tl;
238  }
239  else
240  {
241  COUNT(tr) += COUNT(tl);
242  LLINK(tr) = random_join_exclusive(tl, LLINK(tr));
243  return tr;
244  }
245  }
246 
247  Node * random_remove(Node *& root, const Key & key) noexcept
248  {
249  if (root == Node::NullPtr)
250  return Node::NullPtr;
251 
252  Node * ret_val;
253  if (cmp(key, KEY(root)))
254  {
255  ret_val = random_remove(LLINK(root), key);
256  if (ret_val != Node::NullPtr)
257  COUNT(root)--;
258 
259  return ret_val;
260  }
261  else if (cmp(KEY(root), key))
262  {
263  ret_val = random_remove(RLINK(root), key);
264  if (ret_val != Node::NullPtr)
265  COUNT(root)--;
266 
267  return ret_val;
268  }
269 
270  // key was found
271  ret_val = root;
272  root = random_join_exclusive(LLINK(root), RLINK(root));
273  ret_val->reset();
274 
275  return ret_val;
276  }
277 
278 public:
279 
286  Node * remove(const Key & key) noexcept
287  {
288  Node * ret_val = random_remove(tree_root, key);
289 
290  return ret_val != Node::NullPtr ? ret_val : nullptr;
291  }
292 
299  Node * search(const Key & key) const noexcept
300  {
301  Node * retVal = searchInBinTree<Node, Compare>(tree_root, key, cmp);
302  return retVal == Node::NullPtr ? nullptr : retVal;
303  }
304 
317  Node * search_or_insert(Node * p) noexcept
318  {
319  assert(p != Node::NullPtr);
320  assert(COUNT(p) == 1);
321 
322  Node * result = search(KEY(p));
323  if (result != nullptr)
324  return result;
325 
326  tree_root = random_insert(tree_root, p);
327 
328  return p;
329  }
330 
332  bool verify() const
333  {
334  return check_rank_tree(tree_root);
335  }
336 
338  Node *& getRoot() noexcept { return tree_root; }
339 
347  Node * select(const size_t i) const
348  {
349  return Aleph::select(tree_root, i);
350  }
351 
353  size_t size() const noexcept { return COUNT(tree_root); }
354 
364  std::pair<long, Node*> position(const Key & key) noexcept
365  {
366  std::pair<long, Node*> ret_val;
367  ret_val.first = BinTreeXt_Operation<Node, Compare> (cmp).
368  inorder_position(tree_root, key, ret_val.second);
369 
370  return ret_val;
371  }
372 
399  std::pair<long, Node*> find_position(const Key & key) noexcept
400  {
401  std::pair<long, Node*> r(-2, nullptr);
402 
403  r.first = BinTreeXt_Operation<Node, Compare> (cmp) .
404  find_position(tree_root, key, r.second);
405 
406  return r;
407  }
408 
409 private:
410 
411  Node * remove_pos(Node *& root, const size_t pos) noexcept
412  {
413  if (pos == COUNT(LLINK(root)))
414  {
415  Node * ret_val = root;
416  root = random_join_exclusive(LLINK(ret_val), RLINK(ret_val));
417  return ret_val;
418  }
419 
420  --COUNT(root);
421  if (pos < COUNT(LLINK(root)))
422  return remove_pos(LLINK(root), pos);
423  else
424  return remove_pos(RLINK(root), pos - COUNT(LLINK(root)) - 1);
425  }
426 
427 public:
428 
436  Node * remove_pos(const size_t i) noexcept
437  {
438  if (i >= COUNT(tree_root))
439  throw std::out_of_range("infix position out of range");
440 
441  return remove_pos(tree_root, i);
442  }
443 
452  bool split_key(const Key & key, Gen_Rand_Tree & t1, Gen_Rand_Tree & t2)
453  noexcept
454  {
455  return split_key_rec_xt(tree_root, key, t1.getRoot(), t2.getRoot());
456  }
457 
468  void split_key_dup(const Key & key, Gen_Rand_Tree & t1, Gen_Rand_Tree & t2)
469  noexcept
470  {
471  split_key_dup_rec_xt(tree_root, key, t1.getRoot(), t2.getRoot());
472  }
473 
485  void split_pos(size_t pos, Gen_Rand_Tree & t1, Gen_Rand_Tree & t2) noexcept
486  {
487  split_pos_rec(tree_root, pos, t1.getRoot(), t2.getRoot());
488  }
489 
490 private:
491 
492  Node * random_join(Node * t1, Node * t2, Node *& dup)
493  {
494  if (t1 == Node::NullPtr)
495  return t2;
496 
497  if (t2 == Node::NullPtr)
498  return t1;
499 
500  Node * ret = Node::NullPtr;
501  const size_t & m = COUNT(t1);
502  const size_t & n = COUNT(t2);
503  const size_t rn = 1 + gsl_rng_uniform_int(r, m + n);
504  if (rn <= m)
505  { // root of t1 wins
506  Node * l = LLINK(t1), * r = RLINK(t1);
507  t1->reset();
508  t1_wins:
509  ret = insert_root_xt(t2, t1, cmp);
510  if (ret != Node::NullPtr)
511  {
512  LLINK(ret) = random_join(LLINK(ret), l, dup);
513  RLINK(ret) = random_join(RLINK(ret), r, dup);
514  COUNT(ret) = COUNT(LLINK(ret)) + 1 + COUNT(RLINK(ret));
515  }
516  else
517  {
518  dup = random_insert_dup(dup, random_remove(t2, KEY(t1)));
519  goto t1_wins;
520  }
521  }
522  else
523  { // root of t2 wins
524  Node * l = LLINK(t2), * r = RLINK(t2);
525  t2->reset();
526  t2_wins:
527  ret = insert_root_xt(t1, t2, cmp);
528  if (ret != Node::NullPtr)
529  {
530  LLINK(ret) = random_join(l, LLINK(ret), dup);
531  RLINK(ret) = random_join(r, RLINK(ret), dup);
532  COUNT(ret) = COUNT(LLINK(ret)) + 1 + COUNT(RLINK(ret));
533  }
534  else
535  {
536  dup = random_insert_dup(dup, random_remove(t1, KEY(t2)));
537  goto t2_wins;
538  }
539  }
540 
541  return ret;
542  }
543 
544  Node * random_join(Node * t1, Node * t2)
545  {
546  if (t1 == Node::NullPtr)
547  return t2;
548 
549  if (t2 == Node::NullPtr)
550  return t1;
551 
552  Node * ret = Node::NullPtr;
553  const size_t & m = COUNT(t1);
554  const size_t & n = COUNT(t2);
555  const size_t total = m + n;
556  const size_t rn = 1 + gsl_rng_uniform_int(r, total);
557  if (rn <= m)
558  { // root of t1 wins
559  Node * l = LLINK(t1), * r = RLINK(t1);
560  t1->reset();
561  ret = insert_dup_root_xt(t2, t1, cmp);
562  LLINK(ret) = random_join(LLINK(ret), l);
563  RLINK(ret) = random_join(RLINK(ret), r);
564  }
565  else
566  { // root of t2 wins
567  Node * l = LLINK(t2), * r = RLINK(t2);
568  t2->reset();
569  ret = insert_dup_root_xt(t1, t2, cmp);
570  LLINK(ret) = random_join(l, LLINK(ret));
571  RLINK(ret) = random_join(r, RLINK(ret));
572  }
573 
574  COUNT(ret) = total;
575  return ret;
576  }
577 
578 public:
579 
592  void join(Gen_Rand_Tree & t, Gen_Rand_Tree & dup) noexcept
593  {
594  tree_root = random_join(tree_root, t.tree_root, dup.tree_root);
595  t.tree_root = Node::NullPtr;
596  }
597 
606  void join_dup(Gen_Rand_Tree & t) noexcept
607  {
608  tree_root = random_join(tree_root, t.tree_root);
609  t.tree_root = Node::NullPtr;
610  }
611 
623  void join_exclusive(Gen_Rand_Tree & t) noexcept
624  {
625  tree_root = random_join_exclusive(tree_root, t.tree_root);
626  t.tree_root = Node::NullPtr;
627  }
628 
635  struct Iterator : public BinNodeInfixIterator<Node>
636  {
638  };
639 };
640 
675  template <typename Key, class Compare = Aleph::less<Key>>
676 struct Rand_Tree : public Gen_Rand_Tree<RandNode, Key, Compare>
677 {
679  using Base::Base;
680 };
681 
682 
713  template <typename Key, class Compare = Aleph::less<Key>>
714 struct Rand_Tree_Vtl : public Gen_Rand_Tree<RandNodeVtl,Key,Compare>
715 {
717  using Base::Base;
718 };
719 
720 
721 } // end namespace Aleph
722 
723 # endif // TPL_RAND_TREE_H
724 
Definition: tpl_binNodeUtils.H:2445
Compare & key_comp() noexcept
return the comparison criteria
Definition: tpl_rand_tree.H:147
Gen_Rand_Tree(unsigned int seed, Compare __cmp=Compare()) noexcept
Definition: tpl_rand_tree.H:160
Definition: tpl_rand_tree.H:635
void join_exclusive(Gen_Rand_Tree &t) noexcept
Definition: tpl_rand_tree.H:623
Node * insert_root(Node *&root, Node *p, Compare cmp=Compare()) noexcept
Definition: tpl_binNodeUtils.H:1773
auto & COUNT(Node *p) noexcept
Definition: tpl_binNodeXt.H:66
Node * remove_pos(const size_t i) noexcept
Definition: tpl_rand_tree.H:436
gsl_rng * gsl_rng_object() noexcept
Get a pointer to gsl random number generator.
Definition: tpl_rand_tree.H:153
Node * insert_dup(Node *p) noexcept
Definition: tpl_rand_tree.H:211
void split_key_dup_rec_xt(Node *&root, const typename Node::key_type &key, Node *&l, Node *&r, Compare &cmp) noexcept
Definition: tpl_binNodeXt.H:572
void split_key_dup(const Key &key, Gen_Rand_Tree &t1, Gen_Rand_Tree &t2) noexcept
Definition: tpl_rand_tree.H:468
bool split_key(const Key &key, Gen_Rand_Tree &t1, Gen_Rand_Tree &t2) noexcept
Definition: tpl_rand_tree.H:452
Node * search(const Key &key) const noexcept
Definition: tpl_rand_tree.H:299
bool check_rank_tree(Node *root) noexcept
Definition: tpl_binNodeXt.H:896
Definition: tpl_rand_tree.H:676
Node * select(const size_t i) const
Definition: tpl_rand_tree.H:347
Definition: tpl_binTreeOps.H:560
Node::Key_Type & KEY(Node *p) noexcept
Definition: tpl_binNode.H:318
void split_pos_rec(Node *&r, const size_t i, Node *&ts, Node *&tg)
Definition: tpl_binNodeXt.H:710
Node * select(Node *r, const size_t pos)
Definition: tpl_binNodeXt.H:150
std::pair< long, Node * > position(const Key &key) noexcept
Definition: tpl_rand_tree.H:364
Definition: ah-comb.H:35
Gen_Rand_Tree(Compare cmp=Compare()) noexcept
Definition: tpl_rand_tree.H:168
Node * insert_root_xt(Node *&root, Node *p, Compare &cmp) noexcept
Definition: tpl_binNodeXt.H:605
Node *& getRoot() noexcept
Return the tree&#39;s root.
Definition: tpl_rand_tree.H:338
long inorder_position(Node *r, const typename Node::key_type &key, Node *&p, Compare &cmp) noexcept
Definition: tpl_binNodeXt.H:210
Node * insert_dup_root_xt(Node *&root, Node *p, Compare &cmp) noexcept
Definition: tpl_binNodeXt.H:646
Node *& LLINK(Node *p) noexcept
Definition: tpl_binNode.H:298
size_t size() const noexcept
Return the number of nodes that have the tree.
Definition: tpl_rand_tree.H:353
std::pair< long, Node * > find_position(const Key &key) noexcept
Definition: tpl_rand_tree.H:399
void join(Gen_Rand_Tree &t, Gen_Rand_Tree &dup) noexcept
Definition: tpl_rand_tree.H:592
Compare & get_compare() noexcept
Definition: tpl_rand_tree.H:150
Definition: tpl_rand_tree.H:714
Node * insert_dup_root(Node *&root, Node *p, Compare cmp=Compare()) noexcept
Definition: tpl_binNodeUtils.H:1799
bool split_key_rec_xt(Node *&root, const typename Node::key_type &key, Node *&l, Node *&r, Compare &cmp) noexcept
Definition: tpl_binNodeXt.H:512
bool verify() const
Return true if this is a consistent randomized tree.
Definition: tpl_rand_tree.H:332
Node * search_or_insert(Node *p) noexcept
Definition: tpl_rand_tree.H:317
Node * insert(Node *p) noexcept
Definition: tpl_rand_tree.H:191
void join_dup(Gen_Rand_Tree &t) noexcept
Definition: tpl_rand_tree.H:606
void set_seed(unsigned long seed) noexcept
Set the random number generator seed.
Definition: tpl_rand_tree.H:156
Node *& RLINK(Node *p) noexcept
Definition: tpl_binNode.H:307
void split_pos(size_t pos, Gen_Rand_Tree &t1, Gen_Rand_Tree &t2) noexcept
Definition: tpl_rand_tree.H:485
void swap(Gen_Rand_Tree &tree) noexcept
Swap in constant time all the nodes of this with tree
Definition: tpl_rand_tree.H:172
Definition: tpl_rand_tree.H:71

Leandro Rabindranath León