Aleph-w  1.9
General library for algorithms and data structures
tpl_binTreeOps.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 # ifndef TPL_BINTREEOPS_H
28 # define TPL_BINTREEOPS_H
29 
30 # include <tpl_binNodeUtils.H>
31 # include <tpl_binNodeXt.H>
32 
33 namespace Aleph {
34 
40  template <class Node, class Cmp = Aleph::less<typename Node::key_type>>
42 {
43 protected:
44 
45  Cmp cmp;
46 
47 public:
48 
50  Cmp & key_comp() noexcept { return cmp; }
51 
53  Cmp & get_compare() noexcept { return cmp; }
54 
55  using Key = typename Node::key_type;
56 
57  using key_type = typename Node::key_type;
58 
60  BinTree_Operation(Cmp __cmp = Cmp()) noexcept : cmp(__cmp) { /* empty */ }
61 
69  Node * search(Node * root, const Key & key) noexcept
70  {
71  return searchInBinTree(root, key, cmp);
72  }
73 
83  Node * search_parent(Node * root, const Key & key, Node *& parent) noexcept
84  {
85  return Aleph::search_parent<Node, Cmp>(root, key, parent, cmp);
86  }
87 
105  Node * search_rank_parent(Node * root, const Key & key) noexcept
106  {
107  return Aleph::search_rank_parent<Node, Cmp>(root, key, cmp);
108  }
109 
120  Node * insert(Node *& root, Node * p) noexcept
121  {
122  if (root == Node::NullPtr)
123  return root = p;
124 
125  if (cmp(KEY(p), KEY(root))) // ¿p < root?
126  return insert(LLINK(root), p);
127  else if (cmp(KEY(root), KEY(p))) // ¿p > root?
128  return insert(RLINK(root), p);
129 
130  return Node::NullPtr; // clave repetida ==> no hay inserción
131  }
132 
143  Node * insert_dup(Node *& root, Node * p) noexcept
144  {
145  if (root == Node::NullPtr)
146  return root = p;
147 
148  if (cmp(KEY(p), KEY(root))) // ¿p < root?
149  return insert_dup(LLINK(root), p);
150 
151  return insert_dup(RLINK(root), p);
152  }
153 
165  Node * search_or_insert(Node *& r, Node * p) noexcept
166  {
167  if (r == Node::NullPtr)
168  return r = p;
169 
170  if (cmp(KEY(p), KEY(r))) // ¿p < root?
171  return search_or_insert(LLINK(r), p);
172  else if (cmp (KEY(r), KEY(p))) // ¿p > root?
173  return search_or_insert(RLINK(r), p);
174 
175  return r;
176  }
177 
178 private:
179 
180  bool __split_key_rec(Node * root, const Key & key, Node *& ts, Node *& tg)
181  noexcept
182  {
183  if (root == Node::NullPtr)
184  {
185  ts = tg = Node::NullPtr;
186  return true;
187  }
188 
189  if (cmp(key, KEY(root)) ) // ¿key < KEY(root)?
190  if (__split_key_rec(LLINK(root), key, ts, LLINK(root)))
191  {
192  tg = root;
193  return true;
194  }
195  else
196  return false;
197 
198  if (cmp(KEY(root), key) ) // ¿key > KEY(root)?
199  if (__split_key_rec(RLINK(root), key, RLINK(root), tg))
200  {
201  ts = root;
202  return true;
203  }
204 
205  return false;
206  }
207 
208 public:
209 
225  bool split_key_rec(Node *& root, const Key & key, Node *& ts, Node *& tg)
226  noexcept
227  {
228  bool ret = __split_key_rec(root, key, ts, tg);
229  if (ret)
230  root = Node::NullPtr;
231  return ret;
232  }
233 
234 private:
235 
236  void __split_key_dup_rec(Node * root, const typename Node::key_type & key,
237  Node *& ts, Node *& tg) noexcept
238  {
239  if (root == Node::NullPtr)
240  { // key no se encuentra en árbol ==> split tendrá éxito
241  ts = tg = Node::NullPtr;
242  return;
243  }
244 
245  if (cmp(key, KEY(root))) // ¿key < KEY(root)?
246  __split_key_dup_rec(LLINK(root), key, ts, LLINK(root));
247  else if (cmp(KEY(root), key)) // ¿key > KEY(root)?
248  __split_key_dup_rec(RLINK(root), key, RLINK(root), tg);
249  else // key == KEY(root)
250  __split_key_dup_rec(LLINK(root), key, ts, LLINK(root));
251  }
252 
253 public:
254 
266  void split_key_dup_rec(Node * root, const typename Node::key_type & key,
267  Node *& ts, Node *& tg) noexcept
268  {
269  __split_key_dup_rec(root, key, ts, tg);
270  root = Node::NullPtr;
271  }
272 
280  Node * remove(Node *& root, const Key & key) noexcept
281  {
282  if (root == Node::NullPtr)
283  return Node::NullPtr;
284 
285  if (cmp(key, KEY(root))) // ¿key < KEY(root)?
286  return remove(LLINK(root), key);
287  else if (cmp(KEY(root), key)) // ¿key > KEY(root)?
288  return remove(RLINK(root), key);
289 
290  Node * ret_val = root;
291  root = join_exclusive(LLINK(root), RLINK(root));
292 
293  ret_val->reset();
294 
295  return ret_val;
296  }
297 
309  Node * insert_root(Node *& root, Node * p) noexcept
310  {
311  Node * l = Node::NullPtr, * r = Node::NullPtr;
312 
313  if (not split_key_rec(root, KEY(p), l, r))
314  return Node::NullPtr;
315 
316  LLINK(p) = l;
317  RLINK(p) = r;
318  root = p;
319 
320  return root;
321  }
322 
330  Node * insert_dup_root(Node *& root, Node * p) noexcept
331  {
332  split_key_dup_rec(root, KEY(p), LLINK(p), RLINK(p));
333 
334  return root = p;
335  }
336 
347  Node * join_preorder(Node * t1, Node * t2, Node *& dup) noexcept
348  {
349  if (t2 == Node::NullPtr)
350  return t1;
351 
352  Node * l = LLINK(t2);
353  Node * r = RLINK(t2);
354 
355  if (insert(t1, t2) == Node::NullPtr)
356  insert(dup, t2);
357 
358  join_preorder(t1, l, dup);
359  join_preorder(t1, r, dup);
360 
361  return t1;
362  }
363 
375  Node * join(Node * t1, Node * t2, Node *& dup) noexcept
376  {
377  if (t1 == Node::NullPtr)
378  return t2;
379 
380  if (t2 == Node::NullPtr)
381  return t1;
382 
383  Node * l = LLINK(t1);
384  Node * r = RLINK(t1);
385 
386  t1->reset();
387 
388  while (insert_root(t2, t1) == Node::NullPtr)
389  {
390  Node * p = remove(t1, KEY(t1));
391 
392  assert(p != Node::NullPtr);
393 
394  insert(dup, t1);
395  }
396 
397  LLINK(t2) = join(l, LLINK(t2), dup);
398  RLINK(t2) = join(r, RLINK(t2), dup);
399 
400  return t2;
401  }
402 
414  void split_key(Node * root, const Key & key, Node *& l, Node *& r) noexcept
415  {
416  if (root == Node::NullPtr)
417  {
418  l = r = Node::NullPtr;
419  return;
420  }
421 
422  Node ** current_parent = nullptr;
423  Node ** pending_child = nullptr;
424  char current_is_right;
425  if (cmp (key, KEY(root)))
426  {
427  r = root;
428  pending_child = &l;
429  current_is_right = true;
430  }
431  else
432  {
433  l = root;
434  pending_child = &r;
435  current_is_right = false;
436  }
437 
438  Node * current = root;
439  while (current != Node::NullPtr)
440  {
441  if (cmp (key, KEY(current)))
442  { /* current must be in right side */
443  if (not current_is_right)
444  {
445  current_is_right = not current_is_right;
446  *pending_child = *current_parent; /* change of side */
447  pending_child = current_parent;
448  }
449 
450  current_parent = &LLINK(current);
451  }
452  else
453  { /* current must be in left side */
454  if (current_is_right)
455  {
456  current_is_right = not current_is_right;
457  *pending_child = *current_parent; /* change of side */
458  pending_child = current_parent;
459  }
460  current_parent = &RLINK(current);
461  }
462 
463  current = *current_parent;
464  }
465 
466  *pending_child = Node::NullPtr;
467  root = Node::NullPtr;
468  }
469 
480  Node * insert_root_rec(Node * root, Node * p) noexcept
481  {
482  if (root == Node::NullPtr)
483  return p; /* insertion in empty tree */
484 
485  if (cmp(KEY(p), KEY(root)))
486  { /* insert in left subtree */
487  Node *left_branch = insert_root_rec(LLINK(root), p);
488  if (left_branch == Node::NullPtr)
489  return Node::NullPtr;
490 
491  LLINK(root) = left_branch;
492  root = rotate_to_right(root);
493  }
494  else if (cmp(KEY(root), KEY(p)))
495  { /* insert in right subtree */
496  Node *right_branch = insert_root_rec(RLINK(root), p);
497  if (right_branch == Node::NullPtr)
498  return Node::NullPtr;
499 
500  RLINK(root) = right_branch;
501  root = rotate_to_left(root);
502  }
503  else
504  return Node::NullPtr; /* duplicated key */
505 
506  return root;
507  }
508 
516  Node * search_or_insert_root_rec(Node * root, Node * p) noexcept
517  {
518  if (root == Node::NullPtr)
519  return p; // insertion in empty tree
520 
521  if (cmp(KEY(p), KEY(root)))
522  { // insert in left subtree
523  Node * left_branch = search_or_insert_root_rec(LLINK(root), p);
524  if (left_branch == p) // ¿hubo inserción?
525  {
526  LLINK(root) = left_branch;
527  root = rotate_to_right(root);
528 
529  return p;
530  }
531 
532  return left_branch; // no la hubo
533  }
534  else if (cmp(KEY(root), KEY(p)))
535  { // insert in right subtree
536  Node * right_branch = search_or_insert_root_rec(RLINK(root), p);
537  if (right_branch == p) // ¿hubo inserción?
538  {
539  RLINK(root) = right_branch;
540  root = rotate_to_left(root);
541 
542  return p;
543  }
544 
545  return right_branch; // no la hubo
546  }
547 
548  return root;
549  }
550 };
551 
552 
558  template <class Node,
559  class Cmp = Aleph::less<typename Node::key_type>>
560 class BinTreeXt_Operation : public BinTree_Operation<Node, Cmp>
561 {
562 public:
563 
564  using Key = typename Node::key_type;
565 
567  BinTreeXt_Operation(Cmp cmp = Cmp()) noexcept
568  : BinTree_Operation<Node, Cmp>(cmp)
569  {
570  // empty
571  }
572 
583  long inorder_position(Node * r, const Key & key, Node *& p) noexcept
584  {
585  assert(COUNT(Node::NullPtr) == 0);
586 
587  if (r == Node::NullPtr)
588  return -1;
589 
590  if (this->cmp(key, KEY(r)))
591  return inorder_position(LLINK(r), key, p);
592  else if (this->cmp(KEY(r), key))
593  {
594  long ret = inorder_position(RLINK(r), key, p);
595  if (ret != -1)
596  return ret + COUNT(LLINK(r)) + 1;
597  return ret;
598  }
599  else
600  {
601  p = r;
602  return COUNT(LLINK(r));
603  }
604  }
605 
629  long find_position(Node * r, const Key & key, Node *& p) noexcept
630  {
631  assert(COUNT(Node::NullPtr) == 0);
632 
633  Node * parent = nullptr;
634  long pos = COUNT(LLINK(r));
635 
636  while (r != Node::NullPtr)
637  if (this->cmp(key, KEY(r)))
638  {
639  parent = r;
640  r = LLINK(r);
641  pos -= (COUNT(RLINK(r)) + 1);
642  }
643  else if (this->cmp(KEY(r), key))
644  {
645  parent = r;
646  r = RLINK(r);
647  pos += COUNT(LLINK(r)) + 1;
648  }
649  else
650  {
651  p = r;
652  return pos;
653  }
654 
655  p = parent;
656 
657  return pos;
658  }
659 
672  bool split_key_rec(Node * root, const Key & key, Node *& l, Node *& r)
673  noexcept
674  {
675  if (root == Node::NullPtr)
676  {
677  l = r = Node::NullPtr;
678  return true;
679  }
680 
681  if (this->cmp(key, KEY(root)))
682  {
683  if (not split_key_rec(LLINK(root), key, l, LLINK(root)))
684  return false;
685 
686  r = root;
687  COUNT(r) -= COUNT(l);
688  }
689  else if (this->cmp(KEY(root), key))
690  {
691  if (not split_key_rec(RLINK(root), key, RLINK(root), r))
692  return false;
693 
694  l = root;
695  COUNT(l) -= COUNT(r);
696  }
697  else
698  return false; // clave duplicada
699 
700  return true;
701  }
702 
714  void split_key_dup_rec(Node * root, const Key & key, Node *& l, Node *& r)
715  noexcept
716  {
717  if (root == Node::NullPtr)
718  {
719  l = r = Node::NullPtr;
720  return;
721  }
722 
723  if (this->cmp(key, KEY(root)))
724  {
725  split_key_dup_rec(LLINK(root), key, l, LLINK(root));
726  r = root;
727  COUNT(r) -= COUNT(l);
728  }
729  else
730  {
731  split_key_dup_rec(RLINK(root), key, RLINK(root), r);
732  l = root;
733  COUNT(l) -= COUNT(r);
734  }
735  }
736 
751  Node * insert_root(Node *& root, Node * p) noexcept
752  {
753  if (root == Node::NullPtr)
754  return p;
755 
756  if (not split_key_rec(root, KEY(p), LLINK(p), RLINK(p)))
757  return Node::NullPtr;
758 
759  COUNT(p) = COUNT(LLINK(p)) + COUNT(RLINK(p)) + 1;
760  root = p;
761 
762  return p;
763  }
764 
776  Node * insert_dup_root(Node *& root, Node * p) noexcept
777  {
778  if (root == Node::NullPtr)
779  return p;
780 
781  split_key_dup_rec(root, KEY(p), LLINK(p), RLINK(p));
782 
783  COUNT(p) = COUNT(LLINK(p)) + COUNT(RLINK(p)) + 1;
784 
785  return root = p;
786  }
787 };
788 
789 } // end namespace Aleph
790 
791 # endif // TPL_BINTREEOPS_H
Node * insert_root(Node *&root, Node *p) noexcept
Definition: tpl_binTreeOps.H:309
Cmp & get_compare() noexcept
Definition: tpl_binTreeOps.H:53
Node * rotate_to_right(Node *p) noexcept
Definition: tpl_binNodeUtils.H:1891
Node * search(Node *root, const Key &key) noexcept
Definition: tpl_binTreeOps.H:69
bool split_key_rec(Node *root, const Key &key, Node *&l, Node *&r) noexcept
Definition: tpl_binTreeOps.H:672
Node * insert(Node *&root, Node *p) noexcept
Definition: tpl_binTreeOps.H:120
auto & COUNT(Node *p) noexcept
Definition: tpl_binNodeXt.H:66
Node * insert_dup(Node *&root, Node *p) noexcept
Definition: tpl_binTreeOps.H:143
Node * search_rank_parent(Node *root, const Key &key) noexcept
Definition: tpl_binTreeOps.H:105
Node * insert_dup_root(Node *&root, Node *p) noexcept
Definition: tpl_binTreeOps.H:330
Node * insert_root(Node *&root, Node *p) noexcept
Definition: tpl_binTreeOps.H:751
Definition: tpl_binTreeOps.H:560
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
Node * join(Node *t1, Node *t2, Node *&dup) noexcept
Definition: tpl_binTreeOps.H:375
BinTree_Operation(Cmp __cmp=Cmp()) noexcept
The type of key.
Definition: tpl_binTreeOps.H:60
Definition: ah-comb.H:35
Node * search_or_insert_root_rec(Node *root, Node *p) noexcept
Definition: tpl_binTreeOps.H:516
void split_key(Node *root, const Key &key, Node *&l, Node *&r) noexcept
Definition: tpl_binTreeOps.H:414
long inorder_position(Node *r, const typename Node::key_type &key, Node *&p, Compare &cmp) noexcept
Definition: tpl_binNodeXt.H:210
Node *& LLINK(Node *p) noexcept
Definition: tpl_binNode.H:298
Node * insert_root_rec(Node *root, Node *p) noexcept
Definition: tpl_binTreeOps.H:480
Node * search_or_insert(Node *&r, Node *p) noexcept
Definition: tpl_binTreeOps.H:165
Node * join_preorder(Node *t1, Node *t2, Node *&dup) noexcept
Definition: tpl_binTreeOps.H:347
BinTreeXt_Operation(Cmp cmp=Cmp()) noexcept
Initialize the functor with comparison criteria cmp
Definition: tpl_binTreeOps.H:567
long inorder_position(Node *r, const Key &key, Node *&p) noexcept
Definition: tpl_binTreeOps.H:583
long find_position(Node *r, const Key &key, Node *&p) noexcept
Definition: tpl_binTreeOps.H:629
void split_key_dup_rec(Node *root, const typename Node::key_type &key, Node *&ts, Node *&tg) noexcept
Definition: tpl_binTreeOps.H:266
Node * rotate_to_left(Node *p) noexcept
Definition: tpl_binNodeUtils.H:1932
Node * join_exclusive(Node *&ts, Node *&tg) noexcept
Definition: tpl_binNodeUtils.H:1708
Cmp & key_comp() noexcept
Return the comarison criteria.
Definition: tpl_binTreeOps.H:50
Node *& RLINK(Node *p) noexcept
Definition: tpl_binNode.H:307
bool split_key_rec(Node *&root, const Key &key, Node *&ts, Node *&tg) noexcept
Definition: tpl_binTreeOps.H:225
void split_key_dup_rec(Node *root, const Key &key, Node *&l, Node *&r) noexcept
Definition: tpl_binTreeOps.H:714
typename Node::key_type key_type
The type of key.
Definition: tpl_binTreeOps.H:57
Definition: tpl_binTreeOps.H:41
Node * search_parent(Node *root, const Key &key, Node *&parent) noexcept
Definition: tpl_binTreeOps.H:83
Node * insert_dup_root(Node *&root, Node *p) noexcept
Definition: tpl_binTreeOps.H:776

Leandro Rabindranath León