Aleph-w  1.9
General library for algorithms and data structures
tpl_tree_node.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_TREE_H
29 # define TPL_TREE_H
30 
31 # include <stdexcept>
32 # include <dlink.H>
33 # include <ahDry.H>
34 # include <ahIterator.H>
35 # include <ahFunction.H>
36 # include <ahFunctional.H>
37 # include <htlist.H>
38 # include <tpl_dynListStack.H>
39 # include <tpl_dynListQueue.H>
40 # include <tpl_binNode.H>
41 
42 # define ISROOT(p) ((p)->is_root())
43 # define ISLEAF(p) ((p)->is_leaf())
44 # define ISLEFTMOST(p) ((p)->is_leftmost())
45 # define ISRIGHTMOST(p) ((p)->is_rightmost())
46 
47 # define SIBLING_LIST(p) ((p)->get_sibling_list())
48 # define CHILD_LIST(p) ((p)->get_child_list())
49 # define SIBLING_LINK(p) ((p)->get_sibling_list())
50 # define LCHILD(p) ((p)->get_left_child())
51 # define RSIBLING(p) ((p)->get_right_sibling())
52 # define IS_UNIQUE_SIBLING(p) (RSIBLING(p) == (p))
53 
54 namespace Aleph
55 {
56 
66  template <class T>
67 class Tree_Node
68 {
69  T data;
70  Dlink child;
71  Dlink sibling;
72 
73  struct Flags
74  {
75  unsigned int is_root : 1;
76  unsigned int is_leaf : 1;
77  unsigned int is_leftmost : 1;
78  unsigned int is_rightmost : 1;
79  Flags() noexcept
80  : is_root(1), is_leaf(1), is_leftmost(1), is_rightmost(1) {}
81  };
82 
83  Flags flags;
84 
86  LINKNAME_TO_TYPE(Tree_Node, sibling);
87 
88  Tree_Node * upper_link() const noexcept
89  {
90  return child_to_Tree_Node(child.get_prev());
91  }
92 
93  Tree_Node * lower_link() const noexcept
94  {
95  return child_to_Tree_Node(child.get_next());
96  }
97 
98  Tree_Node * left_link() const noexcept
99  {
100  return sibling_to_Tree_Node(sibling.get_prev());
101  }
102 
103  Tree_Node * right_link() const noexcept
104  {
105  return sibling_to_Tree_Node(sibling.get_next());
106  }
107 
108 public:
109 
110  using Item_Type = Tree_Node*;
111 
113  T & get_key() noexcept { return get_data(); }
114 
115  const T & get_key() const noexcept { return get_data(); }
116 
118  T & get_data() noexcept { return data; }
119 
120  const T & get_data() const noexcept { return data; }
121 
123  using key_type = T;
124 
125  Dlink * get_child_list() noexcept { return &child; }
126 
127  Dlink * get_sibling_list() noexcept { return &sibling; }
128 
130  bool is_root() const noexcept { return flags.is_root; }
131 
133  bool is_leaf() const noexcept { return flags.is_leaf; }
134 
136  bool is_leftmost() const noexcept { return flags.is_leftmost; }
137 
139  bool is_rightmost() const noexcept { return flags.is_rightmost; }
140 
141  void set_is_root(bool value) noexcept { flags.is_root = value; }
142 
143  void set_is_leaf(bool value) noexcept { flags.is_leaf = value; }
144 
145  void set_is_leftmost(bool value) noexcept { flags.is_leftmost = value; }
146 
147  void set_is_rightmost(bool value) noexcept { flags.is_rightmost = value; }
148 
150  Tree_Node() noexcept { /* empty */ }
151 
153  Tree_Node(const T & __data)
154  noexcept(std::is_nothrow_copy_constructible<T>::value)
155  : data(__data) { /* empty */ }
156 
157  Tree_Node(T && __data)
158  noexcept(std::is_nothrow_move_constructible<T>::value)
159  : data(std::move(__data)) { /* empty */ }
160 
162  Tree_Node * get_left_sibling() const noexcept
163  {
164  if (is_leftmost())
165  return nullptr;
166 
167  return left_link();
168  }
169 
171  Tree_Node * get_right_sibling() const noexcept
172  {
173  if (is_rightmost())
174  return nullptr;
175 
176  return right_link();
177  }
178 
180  Tree_Node * get_left_child() const noexcept
181  {
182  if (is_leaf())
183  return nullptr;
184 
185  return lower_link();
186  }
187 
189  Tree_Node * get_right_child() const noexcept
190  {
191  if (is_leaf())
192  return nullptr;
193 
194  Tree_Node * left_child = lower_link();
195 
196  assert(ISLEFTMOST(left_child));
197 
198  return left_child->left_link();
199  }
200 
208  Tree_Node * get_child(const size_t i) const noexcept
209  {
210  Tree_Node * c = get_left_child();
211  for (int j = 0; c != nullptr and j < i; ++j)
212  c = c->get_right_sibling();
213 
214  return c;
215  }
216 
218  Tree_Node * get_parent() const noexcept
219  {
220  if (is_root())
221  return nullptr;
222 
223  Tree_Node * p = const_cast<Tree_Node*>(this);
224  while (not ISLEFTMOST(p)) // baje hasta el nodo más a la izquierda
225  p = p->left_link();
226 
227  assert(not ISROOT(p));
228  assert(not CHILD_LIST(p)->is_empty());
229 
230  return p->upper_link();
231  }
232 
239  void insert_right_sibling(Tree_Node * p) noexcept
240  {
241  if (p == nullptr)
242  return;
243 
244  assert(CHILD_LIST(p)->is_empty());
245  assert(SIBLING_LIST(p)->is_empty());
246  assert(p->is_rightmost() and p->is_leftmost() and p->is_root() and
247  p->is_leaf());
248 
249  p->set_is_root(false);
250  p->set_is_leftmost(false);
251 
252  Tree_Node * old_next_node = get_right_sibling();
253  if (old_next_node != nullptr)
254  {
255  assert(not this->is_rightmost());
256  p->set_is_rightmost(false);
257  }
258  else
259  {
260  assert(this->is_rightmost());
261  p->set_is_rightmost(true);
262  }
263 
264  this->set_is_rightmost(false);
265  this->sibling.insert(SIBLING_LIST(p));
266  }
267 
275  {
276  if (p == nullptr)
277  return;
278 
279  if (this->is_root())
280  throw std::domain_error("Cannot insert sibling of a root");
281 
282  assert(CHILD_LIST(p)->is_empty());
283  assert(SIBLING_LIST(p)->is_empty());
284  assert(p->is_rightmost() and p->is_leftmost() and p->is_root() and
285  p->is_leaf());
286 
287  p->set_is_root(false);
288  p->set_is_rightmost(false);
289 
290  Tree_Node * old_prev_node = this->get_left_sibling();
291  if (old_prev_node != nullptr)
292  {
293  assert(not this->is_leftmost());
294  p->set_is_leftmost(false);
295  }
296  else
297  { // this es más a la izq ==> p debe a ser primogénito
298  assert(this->is_leftmost());
299 
300  Tree_Node * parent = this->get_parent();
301 
302  // Busca la raíz del árbol. Para ello buscamnos la hoja de this
303  Tree_Node * leaf = this;
304  while (not leaf->is_leaf())
305  {
306  leaf = leaf->get_left_child();
307  assert(leaf != nullptr);
308  }
309 
310  Tree_Node * root = leaf->lower_link();
311  assert(root != nullptr);
312 
313  Dlink tree = CHILD_LIST(root)->cut_list(CHILD_LIST(this));
314  tree.del();
315  CHILD_LIST(parent)->insert(CHILD_LIST(p));
316  p->set_is_leftmost(true);
317 
318  assert(p->get_parent() == parent);
319  }
320 
321  this->set_is_leftmost(false);
322  this->sibling.append(SIBLING_LIST(p));
323  }
324 
331  void insert_leftmost_child(Tree_Node * p) noexcept
332  {
333  if (p == nullptr)
334  return;
335 
336  assert(CHILD_LIST(p)->is_empty());
337  assert(SIBLING_LIST(p)->is_empty());
338  assert(p->is_rightmost() and p->is_leftmost() and p->is_root() and
339  p->is_leaf());
340 
341  p->set_is_root(false);
342  if (this->is_leaf())
343  {
344  this->set_is_leaf(false);
345  CHILD_LIST(this)->insert(CHILD_LIST(p));
346  }
347  else
348  {
349  Tree_Node * old_left_child = this->lower_link();
350  Tree_Node * leaf = old_left_child;
351  while (not leaf->is_leaf())
352  leaf = leaf->get_left_child();
353 
354  Tree_Node * root = leaf->lower_link();
355  Dlink subtree = CHILD_LIST(root)->cut_list(CHILD_LIST(old_left_child));
356  subtree.del();
357  CHILD_LIST(this)->insert(CHILD_LIST(p));
358  SIBLING_LIST(old_left_child)->append(SIBLING_LIST(p));
359  old_left_child->set_is_leftmost(false);
360  p->set_is_rightmost(false);
361  assert(p->get_right_sibling() == old_left_child);
362  assert(old_left_child->get_left_sibling() == p);
363  }
364  assert(p->is_leftmost());
365  }
366 
374  {
375  if (p == nullptr)
376  return;
377 
378  assert(CHILD_LIST(p)->is_empty());
379  assert(SIBLING_LIST(p)->is_empty());
380  assert(p->is_rightmost() and p->is_leftmost() and p->is_root() and
381  p->is_leaf());
382 
383  p->set_is_root(false);
384 
385  if (this->is_leaf())
386  {
387  this->set_is_leaf(false);
388  CHILD_LIST(this)->insert(CHILD_LIST(p));
389  }
390  else
391  {
392  Tree_Node * old_right_child_node = this->lower_link()->left_link();
393  old_right_child_node->set_is_rightmost(false);
394  p->set_is_leftmost(false);
395  SIBLING_LIST(old_right_child_node)->insert(SIBLING_LIST(p));
396  }
397  }
398 
401  {
402  assert(this->is_root());
403  assert(tree != nullptr);
404  assert(tree->is_root() and tree->is_leftmost() and tree->is_rightmost());
405 
406  tree->set_is_root(false);
407 
408  if (this->is_leaf())
409  {
410  assert(CHILD_LIST(this)->is_empty() and SIBLING_LIST(this)->is_empty());
411  this->set_is_leaf(false);
412  CHILD_LIST(this)->splice(CHILD_LIST(tree));
413  }
414  else
415  {
416  Tree_Node * right_child = this->lower_link()->left_link();
417  right_child->set_is_rightmost(false);
418  tree->set_is_leftmost(false);
419  SIBLING_LINK(right_child)->splice(SIBLING_LINK(tree));
420  }
421 
422  return this;
423  }
424 
438  {
439  if (tree == nullptr)
440  return;
441 
442  if (not this->is_root())
443  throw std::domain_error("\"this\" is not root");
444 
445  tree->set_is_leftmost(false);
446  Tree_Node * old_next_tree = this->get_right_tree();
447  if (old_next_tree != nullptr)
448  {
449  assert(not this->is_rightmost());
450  tree->set_is_rightmost(false);
451  }
452 
453  this->set_is_rightmost(false);
454  SIBLING_LIST(this)->insert(SIBLING_LIST(tree));
455  }
456 
458  Tree_Node * get_left_tree() const noexcept
459  {
460  if (is_leftmost())
461  return nullptr;
462  assert(not is_leftmost());
463  return left_link();
464  }
465 
467  Tree_Node * get_right_tree() const noexcept
468  {
469  if (is_rightmost())
470  return nullptr;
471 
472  assert(not is_rightmost());
473  return right_link();
474  }
475 
480  {
481  if (not is_leftmost())
482  throw std::range_error("\"this\" is not the leftmost tree in the forest");
483 
484  return left_link();
485  }
486 
488  template <template <typename> class Container = DynList>
489  Container<Tree_Node*> trees() const
490  {
491  Container<Tree_Node*> ret;
492  for (auto t = const_cast<Tree_Node*>(this); t != nullptr;
493  t = t->get_right_tree())
494  ret.append(t);
495  return ret;
496  }
497 
500  template <typename Operation>
501  void for_each_child(Operation & op) const
502  {
503  for (Tree_Node * child = get_left_child(); child != nullptr;
504  child = child->get_right_sibling())
505  op(child);
506  }
507 
508  template <typename Operation>
509  void for_each_child(Operation && op = Operation()) const
510  {
511  for_each_child<Operation>(op);
512  }
513 
515  template <template <typename> class Container = DynList>
516  Container<Tree_Node*> children_nodes() const
517  {
518  Container<Tree_Node*> ret_val;
519  this->for_each_child([&ret_val] (Tree_Node * p) { ret_val.append(p); });
520  return ret_val;
521  }
522 
524  template <template <typename> class Container = DynList>
525  Container<T> children() const
526  {
527  Container<T> ret_val;
528  this->for_each_child([&ret_val] (Tree_Node * p)
529  {
530  ret_val.append(p->get_key());
531  });
532  return ret_val;
533  }
534 
535 private:
536 
537  template <class Operation> static
538  bool preorder(const Tree_Node * root, Operation & op)
539  {
540  if (root == nullptr)
541  return true;
542 
543  if (not op(root))
544  return false;
545 
546  for (Tree_Node * child = root->get_left_child(); child != nullptr;
547  child = child->get_right_sibling())
548  if (not preorder(child, op))
549  return false;
550 
551  return true;
552  }
553 
554 public:
555 
557  template <class Operation>
558  bool traverse(Operation op)
559  {
560  return preorder(this, op);
561  }
562 
563  template <class Operation>
564  bool traverse(Operation op) const
565  {
566  return const_cast<Tree_Node*>(this)->traverse(op);
567  }
568 
569  template <class Op> bool level_traverse(Op op)
570  {
572  q.put(this);
573  while (not q.is_empty())
574  {
575  Tree_Node * p = q.get();
576  if (not op(p))
577  return false;
578  p->for_each_child([&q] (auto cptr) { q.put(cptr); });
579  }
580  return false;
581  }
582 
583  template <class Op> bool level_traverse(Op op) const
584  {
585  return const_cast<Tree_Node*>(this)->level_traverse(op);
586  }
587 
588  Functional_Methods(Tree_Node*);
589 
594  {
595  Tree_Node * curr = nullptr;
596 
597  public:
598 
599  Children_Iterator(const Tree_Node & p) noexcept
600  : curr(p.get_left_child()) {}
601 
602  Children_Iterator(Tree_Node & p) noexcept
603  : curr(p.get_left_child()) {}
604 
605  Children_Iterator(Tree_Node * p) noexcept
606  : curr(p->get_left_child()) {}
607 
608  Children_Iterator(const Children_Iterator & it) noexcept
609  : curr(const_cast<Children_Iterator&>(it).curr) {}
610 
611  bool has_curr() const noexcept { return curr != nullptr; }
612 
613  Tree_Node * get_curr_ne() const noexcept { return curr; }
614 
615  Tree_Node * get_curr() const
616  {
617  if (curr == nullptr)
618  throw std::overflow_error("Children_Iterator::get_curr()");
619  return get_curr_ne();
620  }
621 
622  void next_ne() noexcept { curr = curr->get_right_sibling(); }
623 
624  void next()
625  {
626  if (curr == nullptr)
627  throw std::overflow_error("Children_Iterator::next()");
628  next_ne();
629  }
630  };
631 
632  Children_Iterator children_it() const
633  {
634  return Children_Iterator(*this);
635  }
636 
637  struct Children_Set // truco para usar Pair_Iterator
638  {
639  Children_Set(const Tree_Node &&) {}
640  Children_Set(const Tree_Node &) {}
641  struct Iterator : public Children_Iterator
642  {
643  using Children_Iterator::Children_Iterator;
644  };
645  };
646 
647  class Iterator
648  {
649  Tree_Node * root = nullptr;
650  Tree_Node * curr = nullptr;
651  long pos = 0;
653 
654  public:
655 
656  using Item_Type = Tree_Node*;
657 
658  void swap(Iterator & it)
659  {
660  std::swap(root, it.root);
661  std::swap(curr, it.curr);
662  std::swap(pos, it.pos);
663  s.swap(it.s);
664  }
665 
666  Iterator(Tree_Node * __root = nullptr) noexcept
667  : root(__root), curr(root)
668  {
669  // empty
670  }
671 
672  Iterator(Tree_Node & root) : Iterator(&root) {}
673 
674  Iterator(const Iterator & it)
675  : root(it.root), curr(it.curr), pos(it.pos), s(it.s)
676  {
677  // empty
678  }
679 
680  Iterator(Iterator && it) { swap(it); }
681 
682  Iterator & operator = (const Iterator & it)
683  {
684  if (this == &it)
685  return *this;
686 
687  root = it.root;
688  curr = it.curr;
689  pos = it.pos;
690  s = it.s;
691  return *this;
692  }
693 
694  Iterator & operator = (Iterator && it)
695  {
696  swap(it);
697  return *this;
698  }
699 
700  void reset_first() noexcept
701  {
702  s.empty();
703  curr = root;
704  }
705 
706  bool has_curr() const noexcept { return curr != nullptr; }
707 
708  Tree_Node * get_curr_ne() const noexcept { return curr; }
709 
710  Tree_Node * get_curr() const
711  {
712  if (not has_curr())
713  throw std::overflow_error("Iterator overflow");
714  return get_curr_ne();
715  }
716 
717  void next_ne() noexcept
718  {
719  ++pos;
720  Tree_Node * lchild = curr->get_left_child();
721  if (lchild == nullptr)
722  {
723  if (s.is_empty())
724  curr = nullptr;
725  else
726  curr = s.pop();
727 
728  return;
729  }
730 
731  for (auto p = curr->get_right_child(); p != lchild;
732  p = p->get_left_sibling())
733  s.push(p);
734 
735  curr = lchild;
736  }
737 
738  void next()
739  {
740  if (not has_curr())
741  throw std::overflow_error("Iterator overflow");
742  next_ne();
743  }
744 
745  void end()
746  {
747  curr = nullptr;
748  s.empty();
749  pos = -1;
750  }
751 
753  // has_curr() == true
754  size_t get_pos() const { return pos; }
755  };
756 
757  Iterator get_it() const
758  {
759  return Iterator(const_cast<Tree_Node*>(this));
760  }
761 
762  STL_ALEPH_ITERATOR(Tree_Node);
763 };
764 
765  template <typename T>
766 struct Tree_Node_Vtl : public Tree_Node<T>
767 {
768  virtual ~Tree_Node_Vtl() {}
769 };
770 
771  template <class Node> static inline
772 void clone_tree(Node * src, Node * tgt)
773 {
774  using It = typename Node::Children_Iterator;
775  for (It it(src); it.has_curr(); it.next_ne())
776  tgt->insert_rightmost_child(new Node(it.get_curr_ne()->get_key()));
777 
778  using PItor = Pair_Iterator<It>;
779  for (PItor itor{It(*src), It(*tgt)}; itor.has_curr(); itor.next_ne())
780  {
781  auto p = itor.get_curr_ne();
782  clone_tree(p.first, p.second);
783  }
784 }
785 
786 template <class Node>
787 Node * clone_tree(Node * root)
788 {
789  if (root == nullptr)
790  return nullptr;
791  Node * ret = new Node(root->get_key());
792  clone_tree(root, ret);
793  return ret;
794 }
795 
796  template <class Node> static inline
797 void __tree_preorder_traversal(Node * root, const int & level,
798  const int & child_index,
799  void (*visitFct)(Node *, int, int))
800 {
801  (*visitFct)(root, level, child_index);
802  Node * child = root->get_left_child();
803  for (int i = 0; child != nullptr; ++i, child = child->get_right_sibling())
804  __tree_preorder_traversal(child, level + 1, i, visitFct);
805 }
806 
829  template <class Node> inline
830 void tree_preorder_traversal(Node * root, void (*visitFct)(Node *, int, int))
831 {
832 
833  if (not root->is_root())
834  throw std::domain_error("root is not root");
835 
836  __tree_preorder_traversal(root, 0, 0, visitFct);
837 }
838 
861  template <class Node> inline
862 void forest_preorder_traversal(Node * root, void (*visitFct)(Node *, int, int))
863 {
864  if (not root->is_root())
865  throw std::domain_error("root is not root");
866 
867  for (/* nada */; root != nullptr; root = root->get_right_tree())
868  {
869  assert(root->is_root());
870  __tree_preorder_traversal(root, 0, 0, visitFct);
871  }
872 }
873 
874  template <class Node> static inline
875 void __tree_postorder_traversal(Node * node, const int & level,
876  const int & child_index,
877  void (*visitFct)(Node *, int, int))
878 {
879  Node * child = node->get_left_child();
880 
881  for (int i = 0; child not_eq nullptr; i++, child = child->get_right_sibling())
882  __tree_postorder_traversal(child, level + 1, i, visitFct);
883 
884  (*visitFct)(node, level, child_index);
885 }
886 
908  template <class Node> inline
909 void tree_postorder_traversal(Node * root, void (*visitFct)(Node *, int, int))
910 {
911  __tree_postorder_traversal(root, 0, 0, visitFct);
912 }
913 
937  template <class Node> inline
938 void forest_postorder_traversal(Node * root, void (*visitFct)(Node *, int, int))
939 {
940  if (not root->is_leftmost())
941  throw std::domain_error("root is not the leftmost node of forest");
942 
943  if (not root->is_root())
944  throw std::domain_error("root is not root");
945 
946  for (/* nada */; root not_eq nullptr; root = root->get_right_sibling())
947  {
948  assert(root->is_root());
949  __tree_postorder_traversal(root, 0, 0, visitFct);
950  }
951 }
952 
957  template <class Node, class Eq>
958 inline bool are_tree_equal(Node * t1, Node * t2, Eq & eq)
959  noexcept(noexcept(eq(t1->get_key(), t2->get_key())))
960 {
961  if (t1 == nullptr)
962  return t2 == nullptr;
963 
964  if (t2 == nullptr)
965  return false;
966 
967  if (not eq(t1->get_key(), t2->get_key()))
968  return false;
969 
970  try
971  {
972  return zipEq(t1->children_nodes(), t2->children_nodes()).all([] (auto p)
973  {
974  return are_tree_equal(p.first, p.second);
975  });
976  }
977  catch (std::length_error)
978  {
979  return false;
980  }
981 }
982 
983  template <class Node,
984  class Eq = std::equal_to<typename Node::key_type>>
985 inline bool are_tree_equal(Node * t1, Node * t2, Eq && eq = Eq())
986  noexcept(noexcept(are_tree_equal<Node, Eq>(t1, t2, eq)))
987 {
988  return are_tree_equal<Node, Eq>(t1, t2, eq);
989 }
990 
999  template <class Node> inline
1000 void destroy_tree(Node * root)
1001 {
1002  if (root == nullptr)
1003  return;
1004 
1005  if (not IS_UNIQUE_SIBLING(root))
1006  SIBLING_LIST(root)->del(); // no ==> sacarlo de lista hermanos
1007 
1008  // recorrer los subárboles de derecha a izquierda
1009  for (Node * p = (Node*) root->get_right_child(); p != nullptr; /* nada */)
1010  {
1011  Node * to_delete = p; // respaldar subárbol a borrar p
1012  p = (Node*) p->get_left_sibling(); // Avanzar p a hermano izquierdo
1013  destroy_tree(to_delete); // eliminar recursivamente árbol
1014  }
1015 
1016  if (root->is_leftmost()) // ¿sacar lista hijos?
1017  CHILD_LIST(root)->del();
1018 
1019  delete root;
1020 }
1021 
1034  template <class Node> inline
1035 void destroy_forest(Node * root)
1036 {
1037  if (root == nullptr)
1038  return;
1039 
1040  if (not root->is_leftmost())
1041  throw std::domain_error("root is not the leftmost tree of forest");
1042 
1043  if (not root->is_root())
1044  throw std::domain_error("root is not root");
1045 
1046  while (root != nullptr) // recorre los árboles de izquierda a derecha
1047  {
1048  Node * to_delete = root; // respalda raíz
1049  root = root->get_right_sibling(); // avanza a siguiente árbol
1050  SIBLING_LIST(to_delete)->del(); // elimine de lista árboles
1051  destroy_tree(to_delete); // Borre el árbol
1052  }
1053 }
1054 
1061  template <class Node>
1062 size_t compute_height(Node * root)
1063 {
1064  if (root == nullptr)
1065  return 0;
1066 
1067  size_t temp_h, max_h = 0;
1068  for (Node * aux = root->get_left_child(); aux != nullptr;
1069  aux = aux->get_right_sibling())
1070  if ((temp_h = compute_height(aux)) > max_h)
1071  max_h = temp_h;
1072 
1073  return max_h + 1;
1074 }
1075 
1076  template <class Node> static inline
1077 Node * __deway_search(Node * node, int path [],
1078  const int & idx, const size_t & size)
1079 {
1080  if (node == nullptr)
1081  return nullptr;
1082 
1083  if (idx > size)
1084  throw std::out_of_range("index out of maximum range");
1085 
1086  if (path[idx] < 0) // verifique si se ha alcanzado el nodo
1087  return node;
1088  // avance hasta el próximo hijo path[0]
1089  Node * child = node->get_left_child();
1090  for (int i = 0; i < path[idx] and child != nullptr; ++i)
1091  child = child->get_right_sibling();
1092 
1093  return __deway_search(child, path, idx + 1, size); // próximo nivel
1094 }
1095 
1109  template <class Node> inline
1110 Node * deway_search(Node * root, int path [], const size_t & size)
1111 {
1112  for (int i = 0; root != nullptr; i++, root = root->get_right_sibling())
1113  if (path[0] == i)
1114  return __deway_search(root, path, 1, size);
1115 
1116  return nullptr;
1117 }
1118 
1119  template <class Node, class Equal> inline static
1120 Node * __search_deway(Node * root, const typename Node::key_type & key,
1121  const size_t & current_level, int deway [],
1122  const size_t & size, size_t & n);
1123 
1146  template <class Node,
1147  class Equal = Aleph::equal_to<typename Node::key_type> > inline
1148 Node * search_deway(Node * root, const typename Node::key_type & key,
1149  int deway [], const size_t & size, size_t & n)
1150 {
1151  n = 1; // valor inicial de longitud de número de Deway
1152 
1153  if (size < n)
1154  throw std::overflow_error("there is no enough space for deway array");
1155 
1156  for (int i = 0; root != nullptr; i++, root = root->get_right_sibling())
1157  {
1158  deway[0] = i;
1159  Node * result =
1160  __search_deway <Node, Equal> (root, key, 0, deway, size, n);
1161  if (result != nullptr)
1162  return result;
1163  }
1164 
1165  return nullptr;
1166 }
1167 
1168  template <class Node, class Equal> inline static
1169 Node * __search_deway(Node * root,
1170  const typename Node::key_type & key,
1171  const size_t & current_level, int deway [],
1172  const size_t & size, size_t & n)
1173 {
1174 
1175  if (current_level >= size)
1176  throw std::overflow_error("there is no enough space for deway array");
1177 
1178  if (root == nullptr)
1179  return nullptr;
1180 
1181  if (Equal()(root->get_key(), key))
1182  {
1183  n = current_level + 1; // longitud del arreglo deway
1184  return root;
1185  }
1186 
1187  Node * child = root->get_left_child();
1188  for (int i = 0; child != nullptr;
1189  i++, child = child->get_right_sibling())
1190  {
1191  deway[current_level + 1] = i;
1192  Node * result = __search_deway <Node, Equal>
1193  (child, key, current_level + 1, deway, size, n);
1194 
1195  if (result!= nullptr)
1196  return result;
1197  }
1198 
1199  return nullptr;
1200 }
1201 
1222  template <class TNode, class BNode>
1223 BNode * forest_to_bin(TNode * root)
1224 {
1225  if (root == nullptr)
1226  return BNode::NullPtr;
1227 
1228  BNode * result = new BNode (root->get_key());
1229  LLINK(result) = forest_to_bin<TNode,BNode>(root->get_left_child());
1230  RLINK(result) = forest_to_bin<TNode,BNode>(root->get_right_sibling());
1231 
1232  return result;
1233 }
1234 
1235  template <class TNode, class BNode> inline static
1236 void insert_child(BNode * lnode, TNode * tree_node)
1237 {
1238  if (lnode == BNode::NullPtr)
1239  return;
1240 
1241  TNode * child = new TNode(KEY(lnode));
1242  tree_node->insert_leftmost_child(child);
1243 }
1244 
1245  template <class TNode, class BNode> inline static
1246 void insert_sibling(BNode * rnode, TNode * tree_node)
1247 {
1248  if (rnode == BNode::NullPtr)
1249  return;
1250 
1251  TNode * sibling = new TNode(KEY(rnode));
1252  tree_node->insert_right_sibling(sibling);
1253 }
1254 
1255  template <class TNode, class BNode> inline static
1256 void bin_to_tree(BNode * broot, TNode * troot)
1257 {
1258  if (broot == BNode::NullPtr)
1259  return;
1260 
1261  insert_child(LLINK(broot), troot);
1262  TNode * left_child = troot->get_left_child();
1263 
1264  bin_to_tree(LLINK(broot), left_child);
1265 
1266  insert_sibling(RLINK(broot), troot);
1267  TNode * right_sibling = troot->get_right_sibling();
1268 
1269  bin_to_tree(RLINK(broot), right_sibling);
1270 }
1271 
1291  template <class TNode, class BNode> inline
1292 TNode * bin_to_forest(BNode * broot)
1293 {
1294  if (broot == BNode::NullPtr)
1295  return nullptr;
1296 
1297  TNode * troot = new TNode (KEY(broot));
1298  bin_to_tree(broot, troot);
1299  return troot;
1300 }
1301 
1302 } // fin namespace Aleph
1303 
1304 # endif // TPL_TREE_H
1305 
T & get_key() noexcept
retorna referencia modificable al contenido del nodo.
Definition: tpl_tree_node.H:113
void empty() noexcept
empty the list
Definition: htlist.H:1598
void for_each_child(Operation &op) const
Definition: tpl_tree_node.H:501
Container< Tree_Node * > trees() const
Return a list with all trees belonging to the forrest.
Definition: tpl_tree_node.H:489
void insert_rightmost_child(Tree_Node *p) noexcept
Definition: tpl_tree_node.H:373
Container< T > children() const
Retorna una lista de los contenidos de los hijos de this.
Definition: tpl_tree_node.H:525
void insert_left_sibling(Tree_Node *p)
Definition: tpl_tree_node.H:274
#define LINKNAME_TO_TYPE(type_name, link_name)
Definition: dlink.H:937
bool is_empty() const noexcept
rioReturn true if this is empty
Definition: tpl_dynListQueue.H:112
Tree_Node * get_right_sibling() const noexcept
Retorna hermano derecho de this.
Definition: tpl_tree_node.H:171
void tree_postorder_traversal(Node *root, void(*visitFct)(Node *, int, int))
Definition: tpl_tree_node.H:909
bool is_leaf() const noexcept
Retorna true si this es un nodo hoja.
Definition: tpl_tree_node.H:133
void destroy_tree(Node *root)
Definition: tpl_tree_node.H:1000
T & push(const T &item)
Definition: htlist.H:1432
bool is_empty() const noexcept
Definition: htlist.H:466
BNode * forest_to_bin(TNode *root)
Definition: tpl_tree_node.H:1223
Definition: tpl_dynListQueue.H:50
Definition: tpl_tree_node.H:67
T & get_data() noexcept
retorna referencia modificable al contenido del nodo.
Definition: tpl_tree_node.H:118
Tree_Node * get_last_tree() const
Definition: tpl_tree_node.H:479
void insert_right_sibling(Tree_Node *p) noexcept
Definition: tpl_tree_node.H:239
Node::Key_Type & KEY(Node *p) noexcept
Definition: tpl_binNode.H:318
Tree_Node * get_left_tree() const noexcept
Retorna el árbol a la izquierda de this.
Definition: tpl_tree_node.H:458
Tree_Node() noexcept
Constructor vacío (clave indefinida).
Definition: tpl_tree_node.H:150
Tree_Node * get_right_tree() const noexcept
Retorna el árbol a la derecha de this.
Definition: tpl_tree_node.H:467
Tree_Node * get_left_sibling() const noexcept
Retorna hermano izquierdo de this.
Definition: tpl_tree_node.H:162
Definition: ah-comb.H:35
TNode * bin_to_forest(BNode *broot)
Definition: tpl_tree_node.H:1292
void insert_leftmost_child(Tree_Node *p) noexcept
Definition: tpl_tree_node.H:331
Node * deway_search(Node *root, int path [], const size_t &size)
Definition: tpl_tree_node.H:1110
Tree_Node(const T &__data) noexcept(std::is_nothrow_copy_constructible< T >::value)
Constructor con valor de dato __data.
Definition: tpl_tree_node.H:153
Node *& LLINK(Node *p) noexcept
Definition: tpl_binNode.H:298
bool level_traverse(Node *root, Operation &operation)
Definition: tpl_binNodeUtils.H:662
bool is_leftmost() const noexcept
Retorna true si this es el nodo más a la izquierda de sus hermanos.
Definition: tpl_tree_node.H:136
void insert_tree_to_right(Tree_Node *tree)
Definition: tpl_tree_node.H:437
Definition: tpl_tree_node.H:593
T pop()
Definition: htlist.H:1543
Node * search_deway(Node *root, const typename Node::key_type &key, int deway [], const size_t &size, size_t &n)
Definition: tpl_tree_node.H:1148
Tree_Node * get_right_child() const noexcept
retorna el hijo más a la derecha de this.
Definition: tpl_tree_node.H:189
Tree_Node * get_parent() const noexcept
Retorna el padre de this.
Definition: tpl_tree_node.H:218
Tree_Node * get_child(const size_t i) const noexcept
Definition: tpl_tree_node.H:208
DynList & swap(DynList &l) noexcept
Definition: htlist.H:1346
void forest_preorder_traversal(Node *root, void(*visitFct)(Node *, int, int))
Definition: tpl_tree_node.H:862
Container< Tree_Node * > children_nodes() const
Retorna una lista de los nodos hijos de this.
Definition: tpl_tree_node.H:516
Definition: ahDry.H:41
bool are_tree_equal(Node *t1, Node *t2, Eq &eq) noexcept(noexcept(eq(t1->get_key(), t2->get_key())))
Definition: tpl_tree_node.H:958
bool is_root() const noexcept
Retorna true si this es la raíz del árbol general.
Definition: tpl_tree_node.H:130
void forest_postorder_traversal(Node *root, void(*visitFct)(Node *, int, int))
Definition: tpl_tree_node.H:938
T get()
Definition: tpl_dynListQueue.H:165
Tree_Node * get_left_child() const noexcept
retorna el hijo más a la izquierda de this.
Definition: tpl_tree_node.H:180
Node *& RLINK(Node *p) noexcept
Definition: tpl_binNode.H:307
char key_type
Tipo de dato genérico que contiene el nodo.
Definition: tpl_tree_node.H:123
bool is_rightmost() const noexcept
Retorna true si this es el nodo más a la derecha de sus hermanos.
Definition: tpl_tree_node.H:139
size_t compute_height(Node *root)
Definition: tpl_tree_node.H:1062
void destroy_forest(Node *root)
Definition: tpl_tree_node.H:1035
bool traverse(Operation op)
Recorre en prefijo todos los nodos y ejecuta op.
Definition: tpl_tree_node.H:558
T & put(const T &data)
The type of element.
Definition: tpl_dynListQueue.H:125
Tree_Node * join(Tree_Node *tree)
join tree as subtree of root this
Definition: tpl_tree_node.H:400
void tree_preorder_traversal(Node *root, void(*visitFct)(Node *, int, int))
Definition: tpl_tree_node.H:830

Leandro Rabindranath León