Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
tpl_binHeap.H
Go to the documentation of this file.
1
2/*
3 Aleph_w
4
5 Data structures & Algorithms
6 version 2.0.0b
7 https://github.com/lrleon/Aleph-w
8
9 This file is part of Aleph-w library
10
11 Copyright (c) 2002-2026 Leandro Rabindranath Leon
12
13 Permission is hereby granted, free of charge, to any person obtaining a copy
14 of this software and associated documentation files (the "Software"), to deal
15 in the Software without restriction, including without limitation the rights
16 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 copies of the Software, and to permit persons to whom the Software is
18 furnished to do so, subject to the following conditions:
19
20 The above copyright notice and this permission notice shall be included in all
21 copies or substantial portions of the Software.
22
23 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 SOFTWARE.
30*/
31
32
98# ifndef TPL_BINHEAP_H
99# define TPL_BINHEAP_H
100
101# include <htlist.H>
102# include <tpl_arrayStack.H>
103# include <tpl_binNode.H>
104# include <tpl_dynListQueue.H>
105
106using namespace Aleph;
107
108namespace Aleph
109{
111 {
112 struct Control_Fields //Defining Control Flags
113 {
114 int is_leaf: 4; // true If the node is leaf
115 int is_left: 4; // true if the node is a left child
116 };
117
118 BinHeapNode_Data *pLink; // Pointer to the parent
120
121 public:
123 {
124 control_fields.is_leaf = true;
125 control_fields.is_left = true;
126 }
127
129
131
133 {
134 control_fields.is_leaf = true;
135 control_fields.is_left = true;
136 }
137 };
138
140
141# define PREV(p) (p->getL())
142# define NEXT(p) (p->getR())
143# define ULINK(p) reinterpret_cast<Node*&>((p)->getU())
144# define IS_LEAF(p) ((p)->get_control_fields().is_leaf)
145# define IS_LEFT(p) ((p)->get_control_fields().is_left)
146# define CTRL_BITS(p) ((p)->get_control_fields())
147
170 template <template <class> class NodeType, typename Key,
171 class Compare = Aleph::less<Key>>
173 {
174 protected:
175 Compare cmp;
176
177 public:
179
180 Compare &key_comp() noexcept { return cmp; }
181
182 Compare &get_compare() noexcept { return cmp; }
183
184 private:
189 size_t num_nodes;
190
191 public:
192 void swap(GenBinHeap & h) noexcept
193 {
194 std::swap(root, h.root);
195 std::swap(last, h.last);
196 std::swap(num_nodes, h.num_nodes);
197 std::swap(cmp, h.cmp);
198 }
199
200 private:
201 static bool is_in_list(Node *p) noexcept
202 {
203 if (IS_LEAF(p))
204 return true;
205
206 return ULINK(LLINK(p)) == RLINK(LLINK(p));
207 }
208
209 static bool has_sibling(Node *p) noexcept
210 {
211 return ULINK(p) != RLINK(p);
212 }
213
214 void swap_with_parent(Node *p) noexcept
215 {
216 assert(num_nodes >= 2);
217 assert(p != root);
218
219 Node *pp = ULINK(p); // padre de p
220
221 const bool p_has_sibling = has_sibling(p);
222 const bool p_is_in_list = is_in_list(p); // p is it in the last level?
223 const bool pp_is_in_list = is_in_list(pp); // p == last & LLINK(pp) == last?
224 const bool p_has_child = not IS_LEAF(p); // Does p have children?
225
226 std::swap(CTRL_BITS(pp), CTRL_BITS(p));
227
228 if (pp == root)
229 root = p;
230
231 Node *ppp = ULINK(pp); // abuelo de p; padre de pp
232
233 ULINK(pp) = p; // Actualizar ULINK
234 ULINK(p) = ppp;
235
236 if (LLINK(ppp) == pp)
237 LLINK(ppp) = p;
238 else
239 RLINK(ppp) = p;
240
241 Node *sp = nullptr; // guarda hermano de p
242 if (p_has_sibling)
243 {
244 sp = p == LLINK(pp) ? RLINK(pp) : LLINK(pp); // hermano de p
245 assert(ULINK(sp) == pp);
246 ULINK(sp) = p;
247 }
248
249 if (p == last) // ¿actualizar last?
250 last = pp;
251
252 if (num_nodes == 2)
253 return;
254
255 Node *lcp = LLINK(p); // respaldo de hijos de p
256 Node *rcp = RLINK(p);
257
258 if (num_nodes == 3)
259 {
260 if (RLINK(pp) == p)
261 {
262 LLINK(lcp) = RLINK(lcp) = pp;
263 RLINK(pp) = lcp;
264 RLINK(p) = pp;
265 }
266 else
267 {
268 LLINK(rcp) = RLINK(rcp) = pp;
269 LLINK(pp) = rcp;
270 LLINK(p) = pp;
271 }
272
273 return;
274 }
275
276 if (not p_is_in_list)
277 {
278 ULINK(lcp) = ULINK(rcp) = pp;
279
280 if (LLINK(pp) == p)
281 {
282 assert(RLINK(pp) == sp);
283 LLINK(p) = pp;
284 RLINK(p) = RLINK(pp);
285 }
286 else
287 {
288 assert(LLINK(pp) == sp);
289 RLINK(p) = pp;
290 LLINK(p) = LLINK(pp);
291 }
292
293 LLINK(pp) = lcp;
294 RLINK(pp) = rcp;
295
296 return;
297 }
298
299 if (not pp_is_in_list)
300 {
301 if (p_has_child)
302 ULINK(LLINK(p)) = pp;
303
304 RLINK(lcp) = LLINK(rcp) = pp;
305
306 if (LLINK(pp) == p)
307 {
308 assert(RLINK(pp) == sp);
309 LLINK(p) = pp;
310 RLINK(p) = RLINK(pp);
311 }
312 else
313 {
314 assert(LLINK(pp) == sp);
315 RLINK(p) = pp;
316 LLINK(p) = LLINK(pp);
317 }
318
319 LLINK(pp) = lcp;
320 RLINK(pp) = rcp;
321
322 return;
323 }
324
325 RLINK(lcp) = pp;
326 LLINK(RLINK(pp)) = p;
327 LLINK(pp) = lcp;
328 RLINK(p) = RLINK(pp);
329 RLINK(pp) = p;
330 LLINK(p) = pp;
331 }
332
333 virtual void sift_up(Node *p) noexcept
334 {
335 while (p != root and cmp(KEY(p), KEY(ULINK(p))))
337 }
338
339 virtual void sift_down(Node *p) noexcept
340 {
341 while (not IS_LEAF(p))
342 {
343 Node *cp = LLINK(p); // guarda el menor hijo de p
344 if (has_sibling(cp))
345 if (cmp(KEY(RLINK(p)), KEY(LLINK(p))))
346 cp = RLINK(p);
347
348 if (cmp(KEY(p), KEY(cp)))
349 return;
350
352 }
353 }
354
356 {
357 assert(num_nodes > 1);
358 assert(ULINK(root) == head);
361
362 if (num_nodes > 3) // caso general
363 {
364 Node *lRoot = LLINK(root);
365 Node *rRoot = RLINK(root);
366 Node *f_last = ULINK(last);
369
370 if (LLINK(f_last) == last)
371 LLINK(f_last) = root;
372 else
373 RLINK(f_last) = root;
374
375 if (RLINK(root) != last)
376 std::swap(ULINK(root), ULINK(last));
377 else
378 {
379 ULINK(root) = last;
380 ULINK(root) = head;
381 }
382
383 std::swap(LLINK(root), LLINK(last));
384 std::swap(RLINK(root), RLINK(last));
385
386 ULINK(lRoot) = ULINK(rRoot) = last;
387
388 LLINK(last) = lRoot;
389 RLINK(last) = rRoot;
390
393
395 }
396 else if (num_nodes == 3) // caso particular con 3 nodos
397 {
398 assert(RLINK(root) == last);
400
401 ULINK(last) = ULINK(root);
402 ULINK(root) = last;
403
404 Node *s_last = LLINK(last);
405 ULINK(s_last) = last;
406
407 LLINK(last) = s_last;
408 RLINK(last) = root;
409
410 LLINK(root) = RLINK(root) = s_last;
412 }
413 else // casos particulares con num_nodes < 3
414 {
415 assert(LLINK(root) == last);
416
417 ULINK(last) = ULINK(root);
418 ULINK(root) = last;
419 RLINK(last) = LLINK(last) = root;
420 RLINK(root) = LLINK(root) = last;
421 }
422
423 std::swap(CTRL_BITS(root), CTRL_BITS(last));
424 std::swap(root, last);
425 }
426
428 {
429 assert(last != root and num_nodes > 0);
431
432 Node *ret_val = last;
433 Node *pp = ULINK(last);
435
436 if (IS_LEFT(last))
437 {
438 IS_LEAF(pp) = true;
439 LLINK(pp) = new_last;
440 }
441 else
442 {
443 RLINK(pp) = RLINK(last);
444 LLINK(RLINK(last)) = pp;
445 }
446
447 RLINK(LLINK(last)) = pp;
448 last = new_last;
449 num_nodes--;
450 ret_val->reset();
451
452 return ret_val;
453 }
454
455 void replace_node(Node *node, Node *new_node) noexcept
456 {
457 assert(node != new_node);
458 assert(node != last);
459
460 // guardar los parientes inmediatos de node
461 Node *parent = ULINK(node);
462 Node *left_child = LLINK(node);
463 Node *right_child = RLINK(node);
464
465 // actualizar los punteros pertenecientes a new_node
466 ULINK(new_node) = parent;
467 LLINK(new_node) = left_child;
468 RLINK(new_node) = right_child;
469
470 // actualizar padre
471 if (IS_LEFT(node))
472 {
473 assert(LLINK(parent) == node);
474 LLINK(parent) = new_node;
475 }
476 else
477 {
478 assert(RLINK(parent) == node);
479 RLINK(parent) = new_node;
480 }
481
482 // Update children
483 if (IS_LEAF(node))
484 {
485 RLINK(left_child) = new_node;
486 LLINK(right_child) = new_node;
487 }
488 else
489 {
490 ULINK(left_child) = new_node;
491
492 if (ULINK(right_child) == node) // Node could have only one child
493 ULINK(right_child) = new_node;
494 else
495 {
497 RLINK(left_child) = new_node;
498 LLINK(right_child) = new_node;
499 }
500 }
501
502 CTRL_BITS(new_node) = CTRL_BITS(node);
503 }
504
505 static void __postorder_delete(Node *p, Node *incomplete_node) noexcept
506 {
507 if (IS_LEAF(p))
508 {
509 delete p;
510 return;
511 }
512
514
515 if (p != incomplete_node)
517
518 delete p;
519 }
520
521 public:
522 Node * getRoot() noexcept { return root; }
523
524 Node * getRoot() const noexcept { return const_cast<Node *>(root); }
525
526 private:
527 template <class Operation>
528 static
530 {
531 if (p == nullptr)
532 return;
533
534 operation(p);
537 }
538
539 template <class Operation>
540 static
542 {
543 if (p == nullptr)
544 return;
545
547 operation(p);
549 }
550
551 template <class Operation>
553 {
554 if (p == nullptr)
555 return true;
556 if (not op(p))
557 return false;
559 return false;
560 return preorder_traverse(advance_right(p), op);
561 }
562
563 public:
564 template <class Operation>
566 {
567 return preorder_traverse(getRoot(), op);
568 }
569
570 template <class Operation>
575
576 template <class Operation>
581
582 template <class Operation>
587
588 template <class Operation>
593
594 private:
595 template <class Op>
597 {
598 if (root == nullptr)
599 return true;
600
602 queue.put(root);
603
604 while (not queue.is_empty())
605 {
606 Node *p = queue.get();
607
608 if (not operation(p))
609 return false;
610
611 Node *c = advance_left(p);
612 if (c == nullptr)
613 continue;
614
615 queue.put(c);
616
617 c = advance_right(p);
618 if (c != nullptr)
619 queue.put(c);
620 }
621
622 return true;
623 }
624
625 public:
626 template <class Op>
628 {
630 }
631
632 GenBinHeap(Compare __cmp = Compare()) noexcept
634 num_nodes(0)
635 {
636 // empty
637 }
638
640 { /* empty */
641 }
642
650 Node * insert(Node *p) noexcept
651 {
652 assert(IS_LEAF(p));
653
654 if (root == nullptr) // Is HEAP empty?
655 { // Yes, initialize
656
657 assert(num_nodes == 0);
658
659 root = p;
660 LLINK(p) = RLINK(p) = p;
661 ULINK(p) = head;
662 IS_LEAF(p) = true;
663 IS_LEFT(p) = false; /* root is right child of header node */
664 last = root;
665 num_nodes = 1;
666 return p;
667 }
668 // inserción general
669 Node *pp = RLINK(last); // padre de actual last
670 LLINK(p) = last;
671 ULINK(p) = pp;
672
673 if (IS_LEFT(last))
674 { // p será hijo derecho
675 IS_LEFT(p) = false;
676 RLINK(p) = RLINK(pp);
677 LLINK(RLINK(pp)) = p;
678 RLINK(pp) = p;
679 }
680 else
681 { // p será hijo izquierdo
682 IS_LEFT(p) = true;
683 RLINK(p) = pp;
684 IS_LEAF(pp) = false; // si p es izquierdo ==> pp era hoja
685 LLINK(pp) = p;
686 }
687
689
690 RLINK(last) = p;
691 last = p;
692 num_nodes++;
693 sift_up(last);
694 return p;
695 }
696
698 {
699 Node *ret_val = root;
700 if (num_nodes == 1)
701 {
702 root = nullptr;
703 ret_val->reset();
704 num_nodes = 0;
705
706 return ret_val;
707 }
708
710 remove_last();
712 ret_val->reset();
713
714 return ret_val;
715 }
716
727 {
728 ah_underflow_error_if(root == nullptr) << "Heap is empty";
729 return getMin_ne();
730 }
731
734 {
735 return getMin();
736 }
737
748 void update(Node *p) noexcept
749 {
750 sift_down(p);
751 sift_up(p);
752 }
753
763 Node * remove(Node *node)
764 {
765 ah_underflow_error_if(root == nullptr) << "Heap is empty";
766
767 if (node == root)
768 return getMin_ne();
769
770 if (node == last)
771 return remove_last();
772
773 Node *p = remove_last();
774
775 if (node == last)
776 {
777 remove_last();
778 insert(p);
779
780 return node;
781 }
782 replace_node(node, p);
783 update(p);
784 node->reset();
785
786 return node;
787 }
788
792 {
793 if (root == nullptr)
794 return;
795
796 if (num_nodes <= 3)
797 {
798 while (not this->is_empty())
799 delete getMin_ne();
800 return;
801 }
802
803 if (IS_LEFT(last))
805 else
806 __postorder_delete(root, nullptr);
807
808 root = nullptr; // reiniciar como si fuese constructor
809 last = &head_node;
810 num_nodes = 0;
811 }
812
816 {
817 ah_underflow_error_if(root == nullptr) << "Heap is empty";
818
819 return root;
820 }
821
822 Node * top() const
823 {
824 ah_underflow_error_if(root == nullptr) << "Heap is empty";
825
826 return const_cast<Node *>(root);
827 }
828
829 const size_t &size() const noexcept { return num_nodes; }
830
831 bool is_empty() const noexcept { return size() == 0; }
832
833 protected:
834 static Node * advance_left(Node *p) noexcept
835 {
836 if (IS_LEAF(p))
837 return nullptr;
838
839 return LLINK(p);
840 }
841
842 static Node * advance_right(Node *p) noexcept
843 {
844 if (IS_LEAF(p))
845 return nullptr;
846
847 if (not has_sibling(LLINK(p)))
848 return nullptr;
849
850 return RLINK(p);
851 }
852
853 virtual bool verify_heap(Node *p) const
854 {
855 Node *left_link = advance_left(p);
856 if (left_link == nullptr)
857 {
858 assert(IS_LEAF(p));
859 return true;
860 }
861
862 if (cmp(KEY(left_link), KEY(p)))
863 return false;
864
865 Node *right_link = advance_right(p);
866 if (right_link == nullptr)
867 return verify_heap(left_link);
868
869 if (cmp(KEY(right_link), KEY(p)))
870 return false;
871
872 return verify_heap(right_link);
873 }
874
875 public:
876 bool verify_heap() const
877 {
878 if (root == nullptr)
879 return true;
880
881 return verify_heap(root);
882 }
883
885 {
886 static const size_t Stack_Size = 64;
887
890 Node *curr = nullptr;
891 size_t pos = 0;
892
893 public:
896
899 {
900 if (h.is_empty())
901 return;
902 curr = h.root;
903 }
904
906 {
907 s.empty();
908 if (heap_ptr->is_empty())
909 curr = nullptr;
910 else
911 curr = heap_ptr->root;
912 pos = 0;
913 }
914
916 {
917 s.empty();
918 if (heap_ptr->is_empty())
919 curr = nullptr;
920 else
921 {
922 auto ptr = heap_ptr->root;
923 curr = ptr;
924 while (true)
925 {
926 ptr = advance_right(ptr);
927 if (ptr == nullptr)
928 break;
929 curr = ptr;
930 }
931 }
932 pos = heap_ptr->num_nodes - 1;
933 }
934
935 bool has_curr() const noexcept { return curr != nullptr; }
936
938
939 Node * get_curr() const
940 {
941 ah_overflow_error_if(not has_curr()) << "Iterator overflow";
942 return get_curr_ne();
943 }
944
946 {
947 ++pos;
948 auto l = advance_left(curr), r = advance_right(curr);
949 if (l != nullptr)
950 {
951 curr = l;
952 if (r != nullptr)
953 s.push(r);
954 return;
955 }
956
957 if (r != nullptr)
958 {
959 curr = r;
960 return;
961 }
962
963 if (s.is_empty())
964 curr = nullptr;
965 else
966 curr = s.pop();
967 }
968
969 void next()
970 {
971 ah_overflow_error_if(not has_curr()) << "Iterator overflow";
972 next_ne();
973 }
974
975 size_t get_pos() const noexcept { return pos; }
976
978 {
979 s.empty();
980 curr = nullptr;
982 }
983 };
984 };
985
1002 template <class Key, typename Compare = Aleph::less<Key>>
1003 struct BinHeap : public GenBinHeap<BinHeapNode, Key, Compare>
1004 {
1007 using GenBinHeap<BinHeapNode, Key, Compare>::GenBinHeap;
1008 };
1009
1027 template <class Key, typename Compare = Aleph::less<Key>>
1028 struct BinHeapVtl : public GenBinHeap<BinHeapNodeVtl, Key, Compare>
1029 {
1032 using GenBinHeap<BinHeapNodeVtl, Key, Compare>::GenBinHeap;
1033 };
1034
1035# undef PREV
1036# undef NEXT
1037# undef ULINK
1038# undef IS_LEAF
1039# undef IS_LEFT
1040# undef CTRL_BITS
1041} // end namespace Aleph
1042# endif // TPL_BINHEAP_H
#define ah_underflow_error_if(C)
Throws std::underflow_error if condition holds.
Definition ah-errors.H:368
#define ah_overflow_error_if(C)
Throws std::overflow_error if condition holds.
Definition ah-errors.H:463
@ KEY
Definition btreepic.C:169
#define PREV(p)
Definition btreepic.C:399
long double h
Definition btreepic.C:154
BinHeapNode_Data *& getU() noexcept
BinHeapNode_Data * pLink
Control_Fields control_fields
Control_Fields & get_control_fields() noexcept
void reset() noexcept
Dynamic queue of elements of generic type T based on single linked list.
T & put(const T &data)
The type of element.
T get()
Remove the oldest item of the queue.
bool is_empty() const noexcept
Return true if this is empty.
Fixed length stack.
T & push(const T &data) noexcept
Push a copy of data
bool is_empty() const noexcept
Return true if stack is empty.
T pop() noexcept
Pop by moving the top of stack.
void empty() noexcept
Empty the stack.
Iterator() noexcept
Default constructor creates an "end" iterator.
Node * get_curr_ne() const noexcept
bool has_curr() const noexcept
void reset_first() noexcept
Iterator(const GenBinHeap &h)
FixedStack< Node * > s
static const size_t Stack_Size
size_t get_pos() const noexcept
Heap genérico de nodos.
bool preorder_traverse(Operation op) const
Node * getRoot() noexcept
bool preorder_traverse(Node *p, Operation op) const
Compare & get_compare() noexcept
void update(Node *p) noexcept
Actualiza prioridad de un nodo contenido en el heap.
virtual bool verify_heap(Node *p) const
bool is_empty() const noexcept
static Node * advance_left(Node *p) noexcept
Node * top() const
void for_each_in_preorder(Operation &&operation=Operation()) const
Node * getMin()
Elimina del heap el nodo de menor prioridad.
static bool is_in_list(Node *p) noexcept
Node * getRoot() const noexcept
Node * remove(Node *node)
Elimina del heap el nodo node.
void for_each_in_inorder(Operation &operation) const
void swap_with_parent(Node *p) noexcept
virtual ~GenBinHeap() noexcept
bool verify_heap() const
static Node * advance_right(Node *p) noexcept
void remove_all_and_delete() noexcept
Borra todos los nodos del heap, invoca a los destructores de los nodos eliminados y libera toda la me...
bool level_traverse(Op operation=Op()) const
void replace_node(Node *node, Node *new_node) noexcept
GenBinHeap(Compare __cmp=Compare()) noexcept
static void __for_each_in_inorder(Node *p, Operation &operation)
virtual void sift_up(Node *p) noexcept
Node * getMin_ne() noexcept
virtual void sift_down(Node *p) noexcept
void swap(GenBinHeap &h) noexcept
void for_each_in_preorder(Operation &operation) const
void swap_root_with_last() noexcept
Compare & key_comp() noexcept
static void __for_each_in_preorder(Node *p, Operation &operation)
static void __postorder_delete(Node *p, Node *incomplete_node) noexcept
Node * insert(Node *p) noexcept
Inserta un nodo en un heap.
Node * top()
Retorna el nodo con menor prioridad según el criterio de comparación especificado en la declaración.
void for_each_in_inorder(Operation &&operation=Operation()) const
static bool has_sibling(Node *p) noexcept
const size_t & size() const noexcept
bool __level_traverse(Node *root, Op &operation) const
NodeType< Key > Node
Node * remove_last() noexcept
void reset() noexcept
Definition htlist.H:516
constexpr Node *& RLINK(Node *p) noexcept
Return the right tree of p.
#define DECLARE_BINNODE(Name, height, Control_Data)
Specify tree node for a binary tree.
constexpr Node *& LLINK(Node *p) noexcept
Return a pointer to left subtree.
Singly linked list implementations with head-tail access.
#define NEXT(p)
Definition htlist.H:59
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
DynList< T > maps(const C &c, Op op)
Classic map operation.
Heap of nodes with virtual destroyer.
Node heap without virtual destructor.
Stack implementations backed by dynamic or fixed arrays.
#define CTRL_BITS(p)
#define ULINK(p)
#define IS_LEAF(p)
#define IS_LEFT(p)
Basic binary tree node definitions.
Dynamic queue implementation based on linked lists.
DynList< int > l