Aleph-w  1.9
General library for algorithms and data structures
tpl_treap.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_TREAP_H
29 # define TPL_TREAP_H
30 
31 # include <gsl/gsl_rng.h>
32 # include <ahFunction.H>
33 # include <tpl_binNodeUtils.H>
34 # include <treapNode.H>
35 # include <tpl_binTreeOps.H>
36 
37 using namespace Aleph;
38 
39 namespace Aleph
40 {
41 
65  template <template <typename> class NodeType, typename Key, class Compare>
66 class Gen_Treap
67 {
68 public:
69 
70  using Node = NodeType<Key>;
71 
72 private:
73 
74  Node head;
75  Node * head_ptr;
76  Node *& tree_root;
77  gsl_rng * r;
78  Compare cmp;
79 
80  void init(unsigned int seed)
81  {
82  PRIO(head_ptr) = Min_Priority;
83  r = gsl_rng_alloc (gsl_rng_mt19937);
84 
85  if (r == nullptr)
86  throw std::bad_alloc();
87 
88  gsl_rng_set(r, seed % gsl_rng_max(r));
89  }
90 
91  public:
92 
94  void set_seed(unsigned long seed) noexcept { gsl_rng_set(r, seed); }
95 
97  void swap (Gen_Treap & tree) noexcept
98  {
99  std::swap(tree_root, tree.tree_root);
100  std::swap(cmp, tree.cmp);
101  std::swap(r, tree.r);
102  }
103 
105  Compare & key_comp() noexcept { return cmp; }
106 
108  Compare & get_compare() noexcept { return key_comp(); }
109 
112  Gen_Treap(unsigned long seed, Compare & __cmp = Compare())
113  : head_ptr(&head), tree_root(RLINK(head_ptr)), r(nullptr), cmp(__cmp)
114  {
115  init(seed);
116  }
117 
120  Gen_Treap(Compare cmp = Compare())
121  : Gen_Treap(time(nullptr), cmp) { /* empty */ }
122 
123  ~Gen_Treap()
124  {
125  if (r != nullptr)
126  gsl_rng_free(r);
127  }
128 
130  gsl_rng * gsl_rng_object() noexcept { return r;}
131 
133  Node *& getRoot() noexcept { return tree_root; }
134 
141  Node * search(const Key & key) const noexcept
142  {
143  Node* ret_val = searchInBinTree(tree_root, key, cmp);
144  return ret_val == Node::NullPtr ? nullptr : ret_val;
145  }
146 
147 private:
148 
149  Node * insert(Node * root, Node * p) noexcept
150  {
151  if (root == Node::NullPtr)
152  return p;
153 
154  Node * insertion_result = nullptr;
155  if (cmp(KEY(p), KEY(root)))
156  {
157  insertion_result = insert(LLINK(root), p);
158  if (insertion_result == Node::NullPtr)
159  return Node::NullPtr;
160 
161  LLINK(root) = insertion_result;
162  if (PRIO(insertion_result) < PRIO(root))
163  return rotate_to_right(root);
164  else
165  return root;
166  }
167  else if (cmp(KEY(root), KEY(p)))
168  {
169  insertion_result = insert(RLINK(root), p);
170  if (insertion_result == Node::NullPtr)
171  return Node::NullPtr;
172 
173  RLINK(root) = insertion_result;
174  if (PRIO(insertion_result) < PRIO(root))
175  return rotate_to_left(root);
176  else
177  return root;
178  }
179 
180  return Node::NullPtr;
181  }
182 
183  Node * search_or_insert (Node *& root, Node * p) noexcept
184  {
185  if (root == Node::NullPtr)
186  return root = p;
187 
188  if (cmp(KEY(p), KEY(root)))
189  {
190  Node * ret = search_or_insert(LLINK(root), p);
191  if (ret == p) // p was inserted?
192  if (PRIO(LLINK(root)) < PRIO(root))
193  root = rotate_to_right (root);
194 
195  return ret;
196  }
197  else if (cmp(KEY(root), KEY(p)))
198  {
199  Node * ret = search_or_insert(RLINK(root), p);
200  if (ret == p) // p was inserted?
201  if (PRIO(RLINK(root)) < PRIO(root))
202  root = rotate_to_left (root);
203 
204  return ret;
205  }
206 
207  return root;
208  }
209 
210  Node * insert_dup(Node * root, Node * p) noexcept
211  {
212  if (root == Node::NullPtr)
213  return p;
214 
215  if (cmp(KEY(p), KEY(root)))
216  {
217  Node * result = LLINK(root) = insert_dup(LLINK(root), p);
218  if (PRIO(result) < PRIO(root))
219  return rotate_to_right(root);
220  else
221  return root;
222  }
223  else
224  {
225  Node * result = RLINK(root) = insert_dup(RLINK(root), p);
226  if (PRIO(result) < PRIO(root))
227  return rotate_to_left(root);
228  else
229  return root;
230  }
231  }
232 
233  public:
234 
244  Node * insert(Node * p) noexcept
245  {
246  assert(p != Node::NullPtr);
247 
248  PRIO(p) = gsl_rng_get(r); // selección aleatoria de prioridad
249  Node * result = insert(tree_root, p);
250  if (result == Node::NullPtr)
251  return nullptr;
252 
253  tree_root = result;
254 
255  return p;
256  }
257 
270  Node * search_or_insert(Node * p) noexcept
271  {
272  assert(p != Node::NullPtr);
273 
274  PRIO(p) = gsl_rng_get(r); // selección aleatoria de prioridad
275 
276  return search_or_insert(tree_root, p);
277  }
278 
286  Node * insert_dup(Node * p) noexcept
287  {
288  assert(p != Node::NullPtr);
289 
290  PRIO(p) = gsl_rng_get(r); // selección aleatoria de prioridad
291  tree_root = insert_dup(tree_root, p);
292 
293  return p;
294  }
295 
297  bool verify() const noexcept { return is_treap(tree_root); }
298 
305  Node * remove(const Key & key) noexcept
306  {
307  Node ** pp = &RLINK(head_ptr);
308  Node * p = tree_root;
309 
310  while (p != Node::NullPtr) // descender buscando la clave
311  if (cmp(key, KEY(p)))
312  {
313  pp = &LLINK(p);
314  p = LLINK(p);
315  }
316  else if (cmp(KEY(p), key))
317  {
318  pp = &RLINK(p);
319  p = RLINK(p);
320  }
321  else
322  break; // encontrada!
323 
324  if (p == Node::NullPtr)
325  return nullptr; // clave no fue encontrada
326 
327  // rotar p hasta que devenga hoja
328  while (not (LLINK(p) == Node::NullPtr and RLINK(p) == Node::NullPtr))
329  if (PRIO(LLINK(p)) < PRIO(RLINK(p)))
330  {
331  *pp = rotate_to_right(p);
332  pp = &RLINK(*pp);
333  }
334  else
335  {
336  *pp = rotate_to_left(p);
337  pp = &LLINK(*pp);
338  }
339 
340  *pp = Node::NullPtr;
341 
342  p->reset();
343 
344  return p;
345  }
346 
347 private:
348 
349  static Node * join_exclusive(Node * t1, Node * t2) noexcept
350  {
351  if (t1 == Node::NullPtr)
352  return t2;
353 
354  if (t2 == Node::NullPtr)
355  return t1;
356 
357  if (PRIO(t1) < PRIO(t2))
358  {
359  RLINK(t1) = join_exclusive(RLINK(t1), t2);
360  return t1;
361  }
362  else
363  {
364  LLINK(t2) = join_exclusive(t1, LLINK(t2));
365  return t2;
366  }
367  }
368 
369  Node * remove(Node *& root, const Key & key) noexcept
370  {
371  if (root == Node::NullPtr)
372  return Node::NullPtr;
373 
374  if (cmp(key, KEY(root)))
375  return remove(LLINK(root), key);
376  else if (cmp(KEY(root), key))
377  return remove(RLINK(root), key);
378 
379  Node * ret = root; // key found!
380  root = join_exclusive(LLINK(root), RLINK(root));
381  ret->reset();
382 
383  return ret;
384  }
385 
386  void join_dup(Node *& t1, Node * t2) noexcept
387  {
388  if (t2 == Node::NullPtr)
389  return;
390 
391  Node * l = LLINK(t2), * r = RLINK(t2);
392  t2->reset();
393  t1 = insert_dup(t1, t2);
394  join_dup(t1, l);
395  join_dup(t1, r);
396  }
397 
398  void join(Node *& t1, Node * t2, Node *& dup) noexcept
399  {
400  if (t2 == Node::NullPtr)
401  return;
402 
403  Node * l = LLINK(t2), * r = RLINK(t2);
404  t2->reset();
405  ins:
406  Node * ret = insert(t1, t2);
407  if (ret == Node::NullPtr)
408  {
409  dup = insert_dup(dup, remove(t1, KEY(t2)));
410  goto ins;
411  }
412 
413  t1 = ret;
414  join(t1, l, dup);
415  join(t1, r, dup);
416  }
417 
418 public:
419 
432  void join(Gen_Treap & t, Gen_Treap & dup) noexcept
433  {
434  join(tree_root, t.tree_root, dup.tree_root);
435  t.tree_root = Node::NullPtr;
436  }
437 
446  void join_dup(Gen_Treap & t) noexcept
447  {
448  join_dup(tree_root, t.tree_root);
449  t.tree_root = Node::NullPtr;
450  }
451 
463  void join_exclusive(Gen_Treap & t) noexcept
464  {
465  tree_root = join_exclusive(tree_root, t.tree_root);
466  t.tree_root = Node::NullPtr;
467  }
468 
477  bool split_key(const Key & key, Gen_Treap & t1, Gen_Treap & t2)
478  {
479  return split_key_rec(tree_root, key, t1.getRoot(), t2.getRoot());
480  }
481 
492  void split_key_dup(const Key & key, Gen_Treap & t1, Gen_Treap & t2)
493  {
494  split_key_dup_rec(tree_root, key, t1.getRoot(), t2.getRoot());
495  }
496 
503  struct Iterator : public BinNodeInfixIterator<Node>
504  {
506  };
507 };
508 
534  template <typename Key, class Compare = Aleph::less<Key>>
535 struct Treap : public Gen_Treap<TreapNode, Key, Compare>
536 {
538  using Base::Base;
539 };
540 
541 
567  template <typename Key, class Compare = Aleph::less<Key>>
568 struct Treap_Vtl : public Gen_Treap<TreapNodeVtl, Key, Compare>
569 {
571  using Base::Base;
572 };
573 
574 
575 } // end namespace Aleph
576 # endif // TPL_TREAP_H
577 
Definition: tpl_binNodeUtils.H:2445
void join(Gen_Treap &t, Gen_Treap &dup) noexcept
Definition: tpl_treap.H:432
Node * rotate_to_right(Node *p) noexcept
Definition: tpl_binNodeUtils.H:1891
bool verify() const noexcept
Return true if this is a consistent treap.
Definition: tpl_treap.H:297
void join_dup(Gen_Treap &t) noexcept
Definition: tpl_treap.H:446
Compare & get_compare() noexcept
Definition: tpl_treap.H:108
Definition: tpl_treap.H:503
gsl_rng * gsl_rng_object() noexcept
Get a pointer to gsl random number generator.
Definition: tpl_treap.H:130
bool split_key_rec(Node *&root, const typename Node::key_type &key, Node *&ts, Node *&tg, Compare cmp=Compare()) noexcept
Definition: tpl_binNodeUtils.H:1643
void set_seed(unsigned long seed) noexcept
Set the random number generator seed.
Definition: tpl_treap.H:94
Node * search(const Key &key) const noexcept
Definition: tpl_treap.H:141
Node * insert(Node *p) noexcept
Definition: tpl_treap.H:244
Node * searchInBinTree(Node *root, const typename Node::key_type &key, Compare cmp=Compare()) noexcept
Definition: tpl_binNodeUtils.H:1323
Node::Key_Type & KEY(Node *p) noexcept
Definition: tpl_binNode.H:318
Definition: ah-comb.H:35
Definition: tpl_treap.H:568
Definition: tpl_treap.H:535
Node *& LLINK(Node *p) noexcept
Definition: tpl_binNode.H:298
Gen_Treap(Compare cmp=Compare())
Definition: tpl_treap.H:120
Gen_Treap(unsigned long seed, Compare &__cmp=Compare())
Definition: tpl_treap.H:112
void swap(Gen_Treap &tree) noexcept
Swap in constant time all the nodes of this with tree
Definition: tpl_treap.H:97
Compare & key_comp() noexcept
return the comparison criteria
Definition: tpl_treap.H:105
Node *& getRoot() noexcept
Return the tree&#39;s root.
Definition: tpl_treap.H:133
Node * search_or_insert(Node *p) noexcept
Definition: tpl_treap.H:270
bool split_key(const Key &key, Gen_Treap &t1, Gen_Treap &t2)
Definition: tpl_treap.H:477
Definition: tpl_treap.H:66
Node * insert_dup(Node *p) noexcept
Definition: tpl_treap.H:286
unsigned long & PRIO(Node *p) noexcept
Definition: treapNode.H:63
void split_key_dup(const Key &key, Gen_Treap &t1, Gen_Treap &t2)
Definition: tpl_treap.H:492
Node * rotate_to_left(Node *p) noexcept
Definition: tpl_binNodeUtils.H:1932
void join_exclusive(Gen_Treap &t) noexcept
Definition: tpl_treap.H:463
void split_key_dup_rec(Node *&root, const typename Node::key_type &key, Node *&ts, Node *&tg, Compare cmp=Compare()) noexcept
Definition: tpl_binNodeUtils.H:1686
Node *& RLINK(Node *p) noexcept
Definition: tpl_binNode.H:307

Leandro Rabindranath León