Aleph-w  1.9
General library for algorithms and data structures
tpl_binHeap.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_BINHEAP_H
29 # define TPL_BINHEAP_H
30 
31 # include <htlist.H>
32 # include <tpl_arrayStack.H>
33 # include <tpl_binNode.H>
34 # include <tpl_dynListQueue.H>
35 
36 using namespace Aleph;
37 
38 namespace Aleph {
39 
40  class BinHeapNode_Data
41  {
42  struct Control_Fields // Definición de banderas de control
43  {
44  int is_leaf : 4; // true si el nodo es hoja
45  int is_left : 4; // true si el nodo es hijo izquierdo
46  };
47 
48  BinHeapNode_Data * pLink; // puntero al padre
49  Control_Fields control_fields;
50 
51  public:
52 
53  BinHeapNode_Data() noexcept : pLink(nullptr)
54  {
55  control_fields.is_leaf = true;
56  control_fields.is_left = true;
57  }
58 
59  BinHeapNode_Data *& getU() noexcept { return pLink; }
60 
61  Control_Fields & get_control_fields() noexcept { return control_fields; }
62 
63  void reset() noexcept
64  {
65  control_fields.is_leaf = true;
66  control_fields.is_left = true;
67  }
68  };
69 
70  DECLARE_BINNODE(BinHeapNode, 64, BinHeapNode_Data);
71 
72 # define PREV(p) (p->getL())
73 # define NEXT(p) (p->getR())
74 # define ULINK(p) reinterpret_cast<Node*&>((p)->getU())
75 # define IS_LEAF(p) ((p)->get_control_fields().is_leaf)
76 # define IS_LEFT(p) ((p)->get_control_fields().is_left)
77 # define CTRL_BITS(p) ((p)->get_control_fields())
78 
101  template <template <class> class NodeType, typename Key,
102  class Compare = Aleph::less<Key>>
104  {
105  protected:
106 
107  Compare cmp;
108 
109  public:
110 
111  using Node = NodeType<Key>;
112 
113  Compare & key_comp() noexcept { return cmp; }
114 
115  Compare & get_compare() noexcept { return cmp; }
116 
117  private:
118 
119  Node head_node;
120  Node * head;
121  Node *& root;
122  Node * last;
123  size_t num_nodes;
124 
125  public:
126 
127  void swap(GenBinHeap & h) noexcept
128  {
129  std::swap(root, h.root);
130  std::swap(last, h.last);
131  std::swap(num_nodes, h.num_nodes);
132  std::swap(cmp, h.cmp);
133  }
134 
135  private:
136 
137  static bool is_in_list(Node * p) noexcept
138  {
139  if (IS_LEAF(p))
140  return true;
141 
142  return ULINK(LLINK(p)) == RLINK(LLINK(p));
143  }
144 
145  static bool has_sibling(Node * p) noexcept
146  {
147  return ULINK(p) != RLINK(p);
148  }
149 
150  void swap_with_parent(Node * p) noexcept
151  {
152  assert(num_nodes >= 2);
153  assert(p != root);
154 
155  Node *pp = ULINK(p); // padre de p
156 
157  const bool p_has_sibling = has_sibling(p);
158  const bool p_is_in_list = is_in_list(p); // p está en último nivel?
159  const bool pp_is_in_list = is_in_list(pp); // p == last & LLINK(pp) == last?
160  const bool p_has_child = not IS_LEAF(p); // p tiene hijos?
161 
162  std::swap(CTRL_BITS(pp), CTRL_BITS(p)); // swap de banderas
163 
164  if (pp == root)
165  root = p;
166 
167  Node *ppp = ULINK(pp); // abuelo de p; padre de pp
168 
169  ULINK(pp) = p; // Actualizar ULINK
170  ULINK(p) = ppp;
171 
172  if (LLINK(ppp) == pp)
173  LLINK(ppp) = p;
174  else
175  RLINK(ppp) = p;
176 
177  Node *sp = nullptr; // guarda hermano de p
178  if (p_has_sibling)
179  {
180  sp = p == LLINK(pp) ? RLINK(pp) : LLINK(pp); // hermano de p
181  assert(ULINK(sp) == pp);
182  ULINK(sp) = p;
183  }
184 
185  if (p == last) // ¿actualizar last?
186  last = pp;
187 
188  if (num_nodes == 2)
189  return;
190 
191  Node *lcp = LLINK(p); // respaldo de hijos de p
192  Node *rcp = RLINK(p);
193 
194  if (num_nodes == 3)
195  {
196  if (RLINK(pp) == p)
197  {
198  LLINK(lcp) = RLINK(lcp) = pp;
199  RLINK(pp) = lcp;
200  RLINK(p) = pp;
201  }
202  else
203  {
204  LLINK(rcp) = RLINK(rcp) = pp;
205  LLINK(pp) = rcp;
206  LLINK(p) = pp;
207  }
208 
209  return;
210  }
211 
212  if (not p_is_in_list)
213  {
214  ULINK(lcp) = ULINK(rcp) = pp;
215 
216  if (LLINK(pp) == p)
217  {
218  assert(RLINK(pp) == sp);
219  LLINK(p) = pp;
220  RLINK(p) = RLINK(pp);
221  }
222  else
223  {
224  assert(LLINK(pp) == sp);
225  RLINK(p) = pp;
226  LLINK(p) = LLINK(pp);
227  }
228 
229  LLINK(pp) = lcp;
230  RLINK(pp) = rcp;
231 
232  return;
233  }
234 
235  if (not pp_is_in_list)
236  {
237  if (p_has_child)
238  ULINK(LLINK(p)) = pp;
239 
240  RLINK(lcp) = LLINK(rcp) = pp;
241 
242  if (LLINK(pp) == p)
243  {
244  assert(RLINK(pp) == sp);
245  LLINK(p) = pp;
246  RLINK(p) = RLINK(pp);
247  }
248  else
249  {
250  assert(LLINK(pp) == sp);
251  RLINK(p) = pp;
252  LLINK(p) = LLINK(pp);
253  }
254 
255  LLINK(pp) = lcp;
256  RLINK(pp) = rcp;
257 
258  return;
259  }
260 
261  RLINK(lcp) = pp;
262  LLINK(RLINK(pp)) = p;
263  LLINK(pp) = lcp;
264  RLINK(p) = RLINK(pp);
265  RLINK(pp) = p;
266  LLINK(p) = pp;
267  }
268 
269  virtual void sift_up(Node * p) noexcept
270  {
271  while (p != root and cmp (KEY(p), KEY(ULINK(p))))
272  swap_with_parent(p);
273  }
274 
275  virtual void sift_down(Node * p) noexcept
276  {
277  while (not IS_LEAF(p))
278  {
279  Node * cp = LLINK(p); // guarda el menor hijo de p
280  if (has_sibling(cp))
281  if (cmp (KEY(RLINK(p)), KEY(LLINK(p))))
282  cp = RLINK(p);
283 
284  if (cmp (KEY(p), KEY(cp)))
285  return;
286 
287  swap_with_parent(cp);
288  }
289  }
290 
291  void swap_root_with_last() noexcept
292  {
293  assert(num_nodes > 1);
294  assert(ULINK(root) == head);
295  assert(not IS_LEAF(root));
296  assert(IS_LEAF(last));
297 
298  if (num_nodes > 3) // caso general
299  {
300  Node * lRoot = LLINK(root);
301  Node * rRoot = RLINK(root);
302  Node * f_last = ULINK(last);
303  Node * prev_last = LLINK(last);
304  Node * next_last = RLINK(last);
305 
306  if (LLINK(f_last) == last)
307  LLINK(f_last) = root;
308  else
309  RLINK(f_last) = root;
310 
311  if (RLINK(root) != last)
312  std::swap(ULINK(root), ULINK(last));
313  else
314  {
315  ULINK(root) = last;
316  ULINK(root) = head;
317  }
318 
319  std::swap(LLINK(root), LLINK(last));
320  std::swap(RLINK(root), RLINK(last));
321 
322  ULINK(lRoot) = ULINK(rRoot) = last;
323 
324  LLINK(last) = lRoot;
325  RLINK(last) = rRoot;
326 
327  PREV(root) = prev_last;
328  NEXT(root) = next_last;
329 
330  NEXT(prev_last) = PREV(next_last) = root;
331  }
332  else if (num_nodes == 3) // caso particular con 3 nodos
333  {
334  assert(RLINK(root) == last);
335  assert(LLINK(last) == LLINK(root) and RLINK(last) == LLINK(root));
336 
337  ULINK(last) = ULINK(root);
338  ULINK(root) = last;
339 
340  Node *s_last = LLINK(last);
341  ULINK(s_last) = last;
342 
343  LLINK(last) = s_last;
344  RLINK(last) = root;
345 
346  LLINK(root) = RLINK(root) = s_last;
347  RLINK(s_last) = LLINK(s_last) = root;
348  }
349  else // casos particulares con num_nodes < 3
350  {
351  assert(LLINK(root) == last);
352 
353  ULINK(last) = ULINK(root);
354  ULINK(root) = last;
355  RLINK(last) = LLINK(last) = root;
356  RLINK(root) = LLINK(root) = last;
357  }
358 
359  std::swap(CTRL_BITS(root), CTRL_BITS(last));
360  std::swap(root, last);
361  }
362 
363  Node * remove_last() noexcept
364  {
365  assert(last != root and num_nodes > 0);
366  assert(IS_LEAF(last));
367 
368  Node * ret_val = last;
369  Node * pp = ULINK(last);
370  Node * new_last = LLINK(last);
371 
372  if (IS_LEFT(last))
373  {
374  IS_LEAF(pp) = true;
375  LLINK(pp) = new_last;
376  }
377  else
378  {
379  RLINK(pp) = RLINK(last);
380  LLINK(RLINK(last)) = pp;
381  }
382 
383  RLINK(LLINK(last)) = pp;
384  last = new_last;
385  num_nodes--;
386  ret_val->reset();
387 
388  return ret_val;
389  }
390 
391  void replace_node(Node * node, Node * new_node) noexcept
392  {
393  assert(node != new_node);
394  assert(node != last);
395 
396  // guardar los parientes inmediatos de node
397  Node * parent = ULINK(node);
398  Node * left_child = LLINK(node);
399  Node * right_child = RLINK(node);
400 
401  // actualizar los punteros pertenecientes a new_node
402  ULINK(new_node) = parent;
403  LLINK(new_node) = left_child;
404  RLINK(new_node) = right_child;
405 
406  // actualizar padre
407  if (IS_LEFT(node))
408  {
409  assert(LLINK(parent) == node);
410  LLINK(parent) = new_node;
411  }
412  else
413  {
414  assert(RLINK(parent) == node);
415  RLINK(parent) = new_node;
416  }
417 
418  // actualizar hijos
419  if (IS_LEAF(node))
420  {
421  RLINK(left_child) = new_node;
422  LLINK(right_child) = new_node;
423  }
424  else
425  {
426  ULINK(left_child) = new_node;
427 
428  if (ULINK(right_child) == node) // node pudiera tener sólo un hijo
429  ULINK(right_child) = new_node;
430  else
431  {
432  assert(left_child == last);
433  RLINK(left_child) = new_node;
434  LLINK(right_child) = new_node;
435  }
436  }
437 
438  CTRL_BITS(new_node) = CTRL_BITS(node);
439  }
440 
441  static void __postorder_delete(Node * p, Node * incomplete_node) noexcept
442  {
443  if (IS_LEAF(p))
444  {
445  delete p;
446  return;
447  }
448 
449  __postorder_delete(LLINK(p), incomplete_node);
450 
451  if (p != incomplete_node)
452  __postorder_delete(RLINK(p), incomplete_node);
453 
454  delete p;
455  }
456 
457  public:
458 
459  Node * getRoot() noexcept { return root; }
460 
461  Node * getRoot() const noexcept { return const_cast<Node*>(root); }
462 
463  private:
464 
465  template <class Operation> static
466  void __for_each_in_preorder(Node * p, Operation & operation)
467  {
468  if (p == nullptr)
469  return;
470 
471  operation(p);
472  __for_each_in_preorder(advance_left(p), operation);
473  __for_each_in_preorder(advance_right(p), operation);
474  }
475 
476  template <class Operation> static
477  void __for_each_in_inorder(Node * p, Operation & operation)
478  {
479  if (p == nullptr)
480  return;
481 
482  __for_each_in_inorder(advance_left(p), operation);
483  operation(p);
484  __for_each_in_inorder(advance_right(p), operation);
485  }
486 
487  template <class Operation>
488  bool preorder_traverse(Node * p, Operation op) const noexcept(noexcept(op))
489  {
490  if (p == nullptr)
491  return true;
492  if (not op(p))
493  return false;
494  if (not preorder_traverse(advance_left(p), op))
495  return false;
496  return preorder_traverse(advance_right(p), op);
497  }
498 
499  public:
500 
501  template <class Operation>
502  bool preorder_traverse(Operation op) const noexcept(noexcept(op))
503  {
504  return preorder_traverse(getRoot(), op);
505  }
506 
507  template <class Operation>
508  void for_each_in_preorder(Operation & operation) const
509  {
510  return __for_each_in_preorder<Operation>(getRoot(), operation);
511  }
512 
513  template <class Operation>
514  void for_each_in_preorder(Operation && operation = Operation()) const
515  {
516  return for_each_in_preorder(operation);
517  }
518 
519  template <class Operation>
520  void for_each_in_inorder(Operation & operation) const
521  {
522  return __for_each_in_inorder<Operation>(getRoot(), operation);
523  }
524 
525  template <class Operation>
526  void for_each_in_inorder(Operation && operation = Operation()) const
527  {
528  return for_each_in_inorder(operation);
529  }
530 
531  private:
532 
533  template <class Op>
534  bool __level_traverse(Node * root, Op & operation) const
535  {
536  if (root == nullptr)
537  return true;
538 
540  queue.put(root);
541 
542  while (not queue.is_empty())
543  {
544  Node * p = queue.get();
545 
546  if (not operation(p))
547  return false;
548 
549  Node * c = advance_left(p);
550  if (c == nullptr)
551  continue;
552 
553  queue.put(c);
554 
555  c = advance_right(p);
556  if (c != nullptr)
557  queue.put(c);
558  }
559 
560  return true;
561  }
562 
563  public:
564 
565  template <class Op>
566  bool level_traverse(Op operation = Op()) const
567  {
568  return __level_traverse(getRoot(), operation);
569  }
570 
571  GenBinHeap(Compare __cmp = Compare()) noexcept
572  : cmp(__cmp), head(&head_node), root(RLINK(head)), last(&head_node),
573  num_nodes(0)
574  {
575  // empty
576  }
577 
578  virtual ~GenBinHeap() noexcept { /* empty */ }
579 
587  Node * insert(Node * p) noexcept
588  {
589  assert(IS_LEAF(p));
590 
591  if (root == nullptr) // ¿heap está vacío?
592  { // Sí, inicialice
593 
594  assert(num_nodes == 0);
595 
596  root = p;
597  LLINK(p) = RLINK(p) = p;
598  ULINK(p) = head;
599  IS_LEAF(p) = true;
600  IS_LEFT(p) = false; /* root is right child of header node */
601  last = root;
602  num_nodes = 1;
603  return p;
604  }
605  // inserción general
606  Node * pp = RLINK(last); // padre de actual last
607  LLINK(p) = last;
608  ULINK(p) = pp;
609 
610  if (IS_LEFT(last))
611  { // p será hijo derecho
612  IS_LEFT(p) = false;
613  RLINK(p) = RLINK(pp);
614  LLINK(RLINK(pp)) = p;
615  RLINK(pp) = p;
616  }
617  else
618  { // p será hijo izquierdo
619  IS_LEFT(p) = true;
620  RLINK(p) = pp;
621  IS_LEAF(pp) = false; // si p es izquierdo ==> pp era hoja
622  LLINK(pp) = p;
623  }
624 
625  assert(not IS_LEAF(pp));
626 
627  RLINK(last) = p;
628  last = p;
629  num_nodes++;
630  sift_up(last);
631  return p;
632  }
633 
634  Node * getMin_ne() noexcept
635  {
636  Node *ret_val = root;
637  if (num_nodes == 1)
638  {
639  root = nullptr;
640  ret_val->reset();
641  num_nodes = 0;
642 
643  return ret_val;
644  }
645 
646  swap_root_with_last();
647  remove_last();
648  sift_down(root);
649  ret_val->reset();
650 
651  return ret_val;
652  }
653 
663  Node * getMin()
664  {
665  if (root == nullptr)
666  throw std::underflow_error ("Heap is empty");
667  return getMin_ne();
668  }
669 
671  Node * getMax()
672  {
673  return getMin();
674  }
675 
686  void update(Node * p) noexcept
687  {
688  sift_down(p);
689  sift_up(p);
690  }
691 
701  Node * remove(Node * node)
702  {
703  if (root == nullptr)
704  throw std::underflow_error ("Heap is empty");
705 
706  if (node == root)
707  return getMin_ne();
708 
709  if (node == last)
710  return remove_last();
711 
712  Node * p = remove_last();
713 
714  if (node == last)
715  {
716  remove_last();
717  insert(p);
718 
719  return node;
720  }
721  replace_node(node, p);
722  update(p);
723  node->reset();
724 
725  return node;
726  }
727 
730  void remove_all_and_delete() noexcept
731  {
732  if (root == nullptr)
733  return;
734 
735  if (num_nodes <= 3)
736  {
737  while (not this->is_empty())
738  delete getMin_ne();
739  return;
740  }
741 
742  if (IS_LEFT(last))
743  __postorder_delete(root, ULINK(last));
744  else
745  __postorder_delete(root, nullptr);
746 
747  root = nullptr; // reiniciar como si fuese constructor
748  last = &head_node;
749  num_nodes = 0;
750  }
751 
754  Node * top()
755  {
756  if (root == nullptr)
757  throw std::underflow_error ("Heap is empty");
758 
759  return root;
760  }
761 
763  const size_t & size() const noexcept { return num_nodes; }
764 
766  bool is_empty() const noexcept { return size() == 0; }
767 
768  protected:
769 
770  static Node * advance_left(Node * p) noexcept
771  {
772  if (IS_LEAF(p))
773  return nullptr;
774 
775  return LLINK(p);
776  }
777 
778  static Node * advance_right(Node * p) noexcept
779  {
780  if (IS_LEAF(p))
781  return nullptr;
782 
783  if (not has_sibling(LLINK(p)))
784  return nullptr;
785 
786  return RLINK(p);
787  }
788 
789  virtual bool verify_heap(Node * p) const
790  {
791  Node * left_link = advance_left(p);
792  if (left_link == nullptr)
793  {
794  assert(IS_LEAF(p));
795  return true;
796  }
797 
798  if (cmp (KEY(left_link), KEY(p)))
799  return false;
800 
801  Node * right_link = advance_right(p);
802  if (right_link == nullptr)
803  return verify_heap(left_link);
804 
805  if (cmp (KEY(right_link), KEY(p)))
806  return false;
807 
808  return verify_heap(right_link);
809  }
810 
811  public:
812 
813  bool verify_heap() const
814  {
815  if (root == nullptr)
816  return true;
817 
818  return verify_heap(root);
819  }
820 
821  class Iterator
822  {
823  static const size_t Stack_Size = 64;
824 
825  GenBinHeap * heap_ptr = nullptr;
827  Node * curr = nullptr;
828  size_t pos = 0;
829 
830  public:
831 
832  Iterator(const GenBinHeap & h)
833  : heap_ptr(&const_cast<GenBinHeap&>(h)), s(Stack_Size)
834  {
835  if (h.is_empty())
836  return;
837  curr = h.root;
838  }
839 
840  void reset_first() noexcept
841  {
842  s.empty();
843  if (heap_ptr->is_empty())
844  curr = nullptr;
845  else
846  curr = heap_ptr->root;
847  pos = 0;
848  }
849 
850  void reset_last() noexcept
851  {
852  s.empty();
853  if (heap_ptr->is_empty())
854  curr = nullptr;
855  else
856  {
857  auto ptr = heap_ptr->root;
858  curr = ptr;
859  while (true)
860  {
861  ptr = advance_right(ptr);
862  if (ptr == nullptr)
863  break;
864  curr = ptr;
865  }
866  }
867  pos = heap_ptr->num_nodes - 1;
868  }
869 
870  bool has_curr() const noexcept { return curr != nullptr; }
871 
872  Node * get_curr_ne() const noexcept { return curr; }
873 
874  Node * get_curr() const
875  {
876  if (not has_curr())
877  throw std::overflow_error("Iterator overflow");
878  return get_curr_ne();
879  }
880 
881  void next_ne() noexcept
882  {
883  ++pos;
884  auto l = advance_left(curr), r = advance_right(curr);
885  if (l != nullptr)
886  {
887  curr = l;
888  if (r != nullptr)
889  s.push(r);
890  return;
891  }
892 
893  if (r != nullptr)
894  {
895  curr = r;
896  return;
897  }
898 
899  if (s.is_empty())
900  curr = nullptr;
901  else
902  curr = s.pop();
903  }
904 
905  void next()
906  {
907  if (not has_curr())
908  throw std::overflow_error("Iterator overflow");
909  next_ne();
910  }
911 
912  size_t get_pos() const noexcept { return pos; }
913 
914  void end() noexcept
915  {
916  s.empty();
917  curr = nullptr;
918  pos = heap_ptr->num_nodes;
919  }
920  };
921  };
922 
939  template <class Key, typename Compare = Aleph::less<Key> >
940  struct BinHeap : public GenBinHeap<BinHeapNode, Key, Compare>
941  {
943  using Node = BinHeapNode<Key>;
945  };
946 
964  template <class Key, typename Compare = Aleph::less<Key> >
965  struct BinHeapVtl : public GenBinHeap<BinHeapNodeVtl, Key, Compare>
966  {
968  using Node = BinHeapNodeVtl<Key>;
970  };
971 
972 # undef PREV
973 # undef NEXT
974 # undef ULINK
975 # undef IS_LEAF
976 # undef IS_LEFT
977 # undef CTRL_BITS
978 } // end namespace Aleph
979 # endif // TPL_BINHEAP_H
980 
Definition: Queue.H:44
T pop() noexcept
Pop by moving the top of stack.
Definition: tpl_arrayStack.H:430
bool is_empty() const noexcept
rioReturn true if this is empty
Definition: tpl_dynListQueue.H:112
Node * insert(Node *p) noexcept
Definition: tpl_binHeap.H:587
Node * top()
Definition: tpl_binHeap.H:754
Definition: tpl_dynListQueue.H:50
Node * getMax()
Definition: tpl_binHeap.H:671
Node::Key_Type & KEY(Node *p) noexcept
Definition: tpl_binNode.H:318
Definition: ah-comb.H:35
Definition: tpl_arrayStack.H:302
void update(Node *p) noexcept
Definition: tpl_binHeap.H:686
Definition: tpl_binHeap.H:103
Node *& LLINK(Node *p) noexcept
Definition: tpl_binNode.H:298
bool is_empty() const noexcept
Return true if stack is empty.
Definition: tpl_arrayStack.H:477
Node * getMin()
Definition: tpl_binHeap.H:663
bool level_traverse(Node *root, Operation &operation)
Definition: tpl_binNodeUtils.H:662
Definition: tpl_binHeap.H:940
Definition: tpl_binHeap.H:965
#define DECLARE_BINNODE(Name, height, Control_Data)
Definition: tpl_binNode.H:232
void empty() noexcept
Empty the stack.
Definition: tpl_arrayStack.H:480
void remove_all_and_delete() noexcept
Definition: tpl_binHeap.H:730
T & push(const T &data) noexcept
Definition: tpl_arrayStack.H:385
const size_t & size() const noexcept
Retorna la cardinalidad del heap.
Definition: tpl_binHeap.H:763
bool is_empty() const noexcept
Retorna true si el heap está vacío.
Definition: tpl_binHeap.H:766
T get()
Definition: tpl_dynListQueue.H:165
Node *& RLINK(Node *p) noexcept
Definition: tpl_binNode.H:307
T & put(const T &data)
The type of element.
Definition: tpl_dynListQueue.H:125

Leandro Rabindranath León