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 <ah-concepts.H>
102# include <htlist.H>
103# include <tpl_arrayStack.H>
104# include <tpl_binNode.H>
105# include <tpl_dynListQueue.H>
106
107using namespace Aleph;
108
109namespace Aleph
110{
112 {
113 struct Control_Fields //Defining Control Flags
114 {
115 int is_leaf: 4; // true If the node is leaf
116 int is_left: 4; // true if the node is a left child
117 };
118
119 BinHeapNode_Data *pLink; // Pointer to the parent
121
122 public:
124 {
125 control_fields.is_leaf = true;
126 control_fields.is_left = true;
127 }
128
130
132
134 {
135 control_fields.is_leaf = true;
136 control_fields.is_left = true;
137 }
138 };
139
141
142# define PREV(p) (p->getL())
143# define NEXT(p) (p->getR())
144# define ULINK(p) reinterpret_cast<Node*&>((p)->getU())
145# define IS_LEAF(p) ((p)->get_control_fields().is_leaf)
146# define IS_LEFT(p) ((p)->get_control_fields().is_left)
147# define CTRL_BITS(p) ((p)->get_control_fields())
148
171 template <template <class> class NodeType, typename Key,
172 class Compare = Aleph::less<Key>>
175 {
176 protected:
177 Compare cmp;
178
179 public:
181
182 Compare &key_comp() noexcept { return cmp; }
183
184 Compare &get_compare() noexcept { return cmp; }
185
186 private:
191 size_t num_nodes;
192
193 public:
194 void swap(GenBinHeap & h) noexcept
195 {
196 std::swap(root, h.root);
197 std::swap(last, h.last);
198 std::swap(num_nodes, h.num_nodes);
199 std::swap(cmp, h.cmp);
200 }
201
202 private:
203 static bool is_in_list(Node *p) noexcept
204 {
205 if (IS_LEAF(p))
206 return true;
207
208 return ULINK(LLINK(p)) == RLINK(LLINK(p));
209 }
210
211 static bool has_sibling(Node *p) noexcept
212 {
213 return ULINK(p) != RLINK(p);
214 }
215
216 void swap_with_parent(Node *p) noexcept
217 {
218 assert(num_nodes >= 2);
219 assert(p != root);
220
221 Node *pp = ULINK(p); // padre de p
222
223 const bool p_has_sibling = has_sibling(p);
224 const bool p_is_in_list = is_in_list(p); // p is it in the last level?
225 const bool pp_is_in_list = is_in_list(pp); // p == last & LLINK(pp) == last?
226 const bool p_has_child = not IS_LEAF(p); // Does p have children?
227
228 std::swap(CTRL_BITS(pp), CTRL_BITS(p));
229
230 if (pp == root)
231 root = p;
232
233 Node *ppp = ULINK(pp); // abuelo de p; padre de pp
234
235 ULINK(pp) = p; // Actualizar ULINK
236 ULINK(p) = ppp;
237
238 if (LLINK(ppp) == pp)
239 LLINK(ppp) = p;
240 else
241 RLINK(ppp) = p;
242
243 Node *sp = nullptr; // guarda hermano de p
244 if (p_has_sibling)
245 {
246 sp = p == LLINK(pp) ? RLINK(pp) : LLINK(pp); // hermano de p
247 assert(ULINK(sp) == pp);
248 ULINK(sp) = p;
249 }
250
251 if (p == last) // ¿actualizar last?
252 last = pp;
253
254 if (num_nodes == 2)
255 return;
256
257 Node *lcp = LLINK(p); // respaldo de hijos de p
258 Node *rcp = RLINK(p);
259
260 if (num_nodes == 3)
261 {
262 if (RLINK(pp) == p)
263 {
264 LLINK(lcp) = RLINK(lcp) = pp;
265 RLINK(pp) = lcp;
266 RLINK(p) = pp;
267 }
268 else
269 {
270 LLINK(rcp) = RLINK(rcp) = pp;
271 LLINK(pp) = rcp;
272 LLINK(p) = pp;
273 }
274
275 return;
276 }
277
278 if (not p_is_in_list)
279 {
280 ULINK(lcp) = ULINK(rcp) = pp;
281
282 if (LLINK(pp) == p)
283 {
284 assert(RLINK(pp) == sp);
285 LLINK(p) = pp;
286 RLINK(p) = RLINK(pp);
287 }
288 else
289 {
290 assert(LLINK(pp) == sp);
291 RLINK(p) = pp;
292 LLINK(p) = LLINK(pp);
293 }
294
295 LLINK(pp) = lcp;
296 RLINK(pp) = rcp;
297
298 return;
299 }
300
301 if (not pp_is_in_list)
302 {
303 if (p_has_child)
304 ULINK(LLINK(p)) = pp;
305
306 RLINK(lcp) = LLINK(rcp) = pp;
307
308 if (LLINK(pp) == p)
309 {
310 assert(RLINK(pp) == sp);
311 LLINK(p) = pp;
312 RLINK(p) = RLINK(pp);
313 }
314 else
315 {
316 assert(LLINK(pp) == sp);
317 RLINK(p) = pp;
318 LLINK(p) = LLINK(pp);
319 }
320
321 LLINK(pp) = lcp;
322 RLINK(pp) = rcp;
323
324 return;
325 }
326
327 RLINK(lcp) = pp;
328 LLINK(RLINK(pp)) = p;
329 LLINK(pp) = lcp;
330 RLINK(p) = RLINK(pp);
331 RLINK(pp) = p;
332 LLINK(p) = pp;
333 }
334
335 virtual void sift_up(Node *p) noexcept
336 {
337 while (p != root and cmp(KEY(p), KEY(ULINK(p))))
339 }
340
341 virtual void sift_down(Node *p) noexcept
342 {
343 while (not IS_LEAF(p))
344 {
345 Node *cp = LLINK(p); // guarda el menor hijo de p
346 if (has_sibling(cp))
347 if (cmp(KEY(RLINK(p)), KEY(LLINK(p))))
348 cp = RLINK(p);
349
350 if (cmp(KEY(p), KEY(cp)))
351 return;
352
354 }
355 }
356
358 {
359 assert(num_nodes > 1);
360 assert(ULINK(root) == head);
363
364 if (num_nodes > 3) // caso general
365 {
366 Node *lRoot = LLINK(root);
367 Node *rRoot = RLINK(root);
368 Node *f_last = ULINK(last);
371
372 if (LLINK(f_last) == last)
373 LLINK(f_last) = root;
374 else
375 RLINK(f_last) = root;
376
377 if (RLINK(root) != last)
378 std::swap(ULINK(root), ULINK(last));
379 else
380 {
381 ULINK(root) = last;
382 ULINK(root) = head;
383 }
384
385 std::swap(LLINK(root), LLINK(last));
386 std::swap(RLINK(root), RLINK(last));
387
388 ULINK(lRoot) = ULINK(rRoot) = last;
389
390 LLINK(last) = lRoot;
391 RLINK(last) = rRoot;
392
395
397 }
398 else if (num_nodes == 3) // special case with 3 nodes
399 {
400 assert(RLINK(root) == last);
402
403 ULINK(last) = ULINK(root);
404 ULINK(root) = last;
405
406 Node *s_last = LLINK(last);
407 ULINK(s_last) = last;
408
409 LLINK(last) = s_last;
410 RLINK(last) = root;
411
412 LLINK(root) = RLINK(root) = s_last;
414 }
415 else // casos particulares con num_nodes < 3
416 {
417 assert(LLINK(root) == last);
418
419 ULINK(last) = ULINK(root);
420 ULINK(root) = last;
421 RLINK(last) = LLINK(last) = root;
422 RLINK(root) = LLINK(root) = last;
423 }
424
425 std::swap(CTRL_BITS(root), CTRL_BITS(last));
426 std::swap(root, last);
427 }
428
430 {
431 assert(last != root and num_nodes > 0);
433
434 Node *ret_val = last;
435 Node *pp = ULINK(last);
437
438 if (IS_LEFT(last))
439 {
440 IS_LEAF(pp) = true;
441 LLINK(pp) = new_last;
442 }
443 else
444 {
445 RLINK(pp) = RLINK(last);
446 LLINK(RLINK(last)) = pp;
447 }
448
449 RLINK(LLINK(last)) = pp;
450 last = new_last;
451 num_nodes--;
452 ret_val->reset();
453
454 return ret_val;
455 }
456
457 void replace_node(Node *node, Node *new_node) noexcept
458 {
459 assert(node != new_node);
460 assert(node != last);
461
462 // save node's immediate relatives
463 Node *parent = ULINK(node);
464 Node *left_child = LLINK(node);
465 Node *right_child = RLINK(node);
466
467 // update new_node's own pointers
468 ULINK(new_node) = parent;
469 LLINK(new_node) = left_child;
470 RLINK(new_node) = right_child;
471
472 // update parent
473 if (IS_LEFT(node))
474 {
475 assert(LLINK(parent) == node);
476 LLINK(parent) = new_node;
477 }
478 else
479 {
480 assert(RLINK(parent) == node);
481 RLINK(parent) = new_node;
482 }
483
484 // Update children
485 if (IS_LEAF(node))
486 {
487 RLINK(left_child) = new_node;
488 LLINK(right_child) = new_node;
489 }
490 else
491 {
492 ULINK(left_child) = new_node;
493
494 if (ULINK(right_child) == node) // Node could have only one child
495 ULINK(right_child) = new_node;
496 else
497 {
498 assert(left_child == last);
499 RLINK(left_child) = new_node;
500 LLINK(right_child) = new_node;
501 }
502 }
503
504 CTRL_BITS(new_node) = CTRL_BITS(node);
505 }
506
507 static void __postorder_delete(Node *p, Node *incomplete_node) noexcept
508 {
509 if (IS_LEAF(p))
510 {
511 delete p;
512 return;
513 }
514
516
517 if (p != incomplete_node)
519
520 delete p;
521 }
522
523 public:
524 Node * getRoot() noexcept { return root; }
525
526 Node * getRoot() const noexcept { return const_cast<Node *>(root); }
527
528 private:
529 template <class Operation>
530 static
532 {
533 if (p == nullptr)
534 return;
535
536 operation(p);
539 }
540
541 template <class Operation>
542 static
544 {
545 if (p == nullptr)
546 return;
547
549 operation(p);
551 }
552
553 template <class Operation>
555 {
556 if (p == nullptr)
557 return true;
558 if (not op(p))
559 return false;
561 return false;
562 return preorder_traverse(advance_right(p), op);
563 }
564
565 public:
566 template <class Operation>
568 {
569 return preorder_traverse(getRoot(), op);
570 }
571
572 template <class Operation>
577
578 template <class Operation>
583
584 template <class Operation>
589
590 template <class Operation>
595
596 private:
597 template <class Op>
599 {
600 if (root == nullptr)
601 return true;
602
604 queue.put(root);
605
606 while (not queue.is_empty())
607 {
608 Node *p = queue.get();
609
610 if (not operation(p))
611 return false;
612
613 Node *c = advance_left(p);
614 if (c == nullptr)
615 continue;
616
617 queue.put(c);
618
619 c = advance_right(p);
620 if (c != nullptr)
621 queue.put(c);
622 }
623
624 return true;
625 }
626
627 public:
628 template <class Op>
629 bool level_traverse(Op operation = Op()) const
630 {
632 }
633
634 GenBinHeap(Compare __cmp = Compare()) noexcept
636 num_nodes(0)
637 {
638 // empty
639 }
640
642 { /* empty */
643 }
644
652 Node * insert(Node *p) noexcept
653 {
654 assert(IS_LEAF(p));
655
656 if (root == nullptr) // Is HEAP empty?
657 { // Yes, initialize
658
659 assert(num_nodes == 0);
660
661 root = p;
662 LLINK(p) = RLINK(p) = p;
663 ULINK(p) = head;
664 IS_LEAF(p) = true;
665 IS_LEFT(p) = false; /* root is right child of header node */
666 last = root;
667 num_nodes = 1;
668 return p;
669 }
670 // general insertion
671 Node *pp = RLINK(last); // parent of the current last
672 LLINK(p) = last;
673 ULINK(p) = pp;
674
675 if (IS_LEFT(last))
676 { // p will be a right child
677 IS_LEFT(p) = false;
678 RLINK(p) = RLINK(pp);
679 LLINK(RLINK(pp)) = p;
680 RLINK(pp) = p;
681 }
682 else
683 { // p will be a left child
684 IS_LEFT(p) = true;
685 RLINK(p) = pp;
686 IS_LEAF(pp) = false; // if p is a left child ==> pp was a leaf
687 LLINK(pp) = p;
688 }
689
691
692 RLINK(last) = p;
693 last = p;
694 num_nodes++;
695 sift_up(last);
696 return p;
697 }
698
700 {
701 Node *ret_val = root;
702 if (num_nodes == 1)
703 {
704 root = nullptr;
705 ret_val->reset();
706 num_nodes = 0;
707
708 return ret_val;
709 }
710
712 remove_last();
714 ret_val->reset();
715
716 return ret_val;
717 }
718
729 {
730 ah_underflow_error_if(root == nullptr) << "Heap is empty";
731 return getMin_ne();
732 }
733
736 {
737 return getMin();
738 }
739
750 void update(Node *p) noexcept
751 {
752 sift_down(p);
753 sift_up(p);
754 }
755
765 Node * remove(Node *node)
766 {
767 ah_underflow_error_if(root == nullptr) << "Heap is empty";
768
769 if (node == root)
770 return getMin_ne();
771
772 if (node == last)
773 return remove_last();
774
775 Node *p = remove_last();
776
777 if (node == last)
778 {
779 remove_last();
780 insert(p);
781
782 return node;
783 }
784 replace_node(node, p);
785 update(p);
786 node->reset();
787
788 return node;
789 }
790
794 {
795 if (root == nullptr)
796 return;
797
798 if (num_nodes <= 3)
799 {
800 while (not this->is_empty())
801 delete getMin_ne();
802 return;
803 }
804
805 if (IS_LEFT(last))
807 else
808 __postorder_delete(root, nullptr);
809
810 root = nullptr; // reset as if it were the constructor
811 last = &head_node;
812 num_nodes = 0;
813 }
814
818 {
819 ah_underflow_error_if(root == nullptr) << "Heap is empty";
820
821 return root;
822 }
823
824 Node * top() const
825 {
826 ah_underflow_error_if(root == nullptr) << "Heap is empty";
827
828 return const_cast<Node *>(root);
829 }
830
831 const size_t &size() const noexcept { return num_nodes; }
832
833 bool is_empty() const noexcept { return size() == 0; }
834
835 protected:
836 static Node * advance_left(Node *p) noexcept
837 {
838 if (IS_LEAF(p))
839 return nullptr;
840
841 return LLINK(p);
842 }
843
844 static Node * advance_right(Node *p) noexcept
845 {
846 if (IS_LEAF(p))
847 return nullptr;
848
849 if (not has_sibling(LLINK(p)))
850 return nullptr;
851
852 return RLINK(p);
853 }
854
855 virtual bool verify_heap(Node *p) const
856 {
857 Node *left_link = advance_left(p);
858 if (left_link == nullptr)
859 {
860 assert(IS_LEAF(p));
861 return true;
862 }
863
864 if (cmp(KEY(left_link), KEY(p)))
865 return false;
866
867 Node *right_link = advance_right(p);
868 if (right_link == nullptr)
869 return verify_heap(left_link);
870
871 if (cmp(KEY(right_link), KEY(p)))
872 return false;
873
874 return verify_heap(right_link);
875 }
876
877 public:
878 bool verify_heap() const
879 {
880 if (root == nullptr)
881 return true;
882
883 return verify_heap(root);
884 }
885
887 {
888 static const size_t Stack_Size = 64;
889
892 Node *curr = nullptr;
893 size_t pos = 0;
894
895 public:
898
901 {
902 if (h.is_empty())
903 return;
904 curr = h.root;
905 }
906
908 {
909 s.empty();
910 if (heap_ptr->is_empty())
911 curr = nullptr;
912 else
913 curr = heap_ptr->root;
914 pos = 0;
915 }
916
918 {
919 s.empty();
920 if (heap_ptr->is_empty())
921 curr = nullptr;
922 else
923 {
924 auto ptr = heap_ptr->root;
925 curr = ptr;
926 while (true)
927 {
928 ptr = advance_right(ptr);
929 if (ptr == nullptr)
930 break;
931 curr = ptr;
932 }
933 }
934 pos = heap_ptr->num_nodes - 1;
935 }
936
937 bool has_curr() const noexcept { return curr != nullptr; }
938
940
941 Node * get_curr() const
942 {
943 ah_overflow_error_if(not has_curr()) << "Iterator overflow";
944 return get_curr_ne();
945 }
946
948 {
949 ++pos;
951 if (l != nullptr)
952 {
953 curr = l;
954 if (r != nullptr)
955 s.push(r);
956 return;
957 }
958
959 if (r != nullptr)
960 {
961 curr = r;
962 return;
963 }
964
965 if (s.is_empty())
966 curr = nullptr;
967 else
968 curr = s.pop();
969 }
970
971 void next()
972 {
973 ah_overflow_error_if(not has_curr()) << "Iterator overflow";
974 next_ne();
975 }
976
977 size_t get_pos() const noexcept { return pos; }
978
980 {
981 s.empty();
982 curr = nullptr;
984 }
985 };
986 };
987
1004 template <class Key, typename Compare = Aleph::less<Key>>
1006 struct BinHeap : public GenBinHeap<BinHeapNode, Key, Compare>
1007 {
1010 using GenBinHeap<BinHeapNode, Key, Compare>::GenBinHeap;
1011 };
1012
1030 template <class Key, typename Compare = Aleph::less<Key>>
1032 struct BinHeapVtl : public GenBinHeap<BinHeapNodeVtl, Key, Compare>
1033 {
1036 using GenBinHeap<BinHeapNodeVtl, Key, Compare>::GenBinHeap;
1037 };
1038
1039# undef PREV
1040# undef NEXT
1041# undef ULINK
1042# undef IS_LEAF
1043# undef IS_LEFT
1044# undef CTRL_BITS
1045} // end namespace Aleph
1046# endif // TPL_BINHEAP_H
C++20 concepts hub: comparison, BST policy, and Aleph container concepts.
#define ah_underflow_error_if(C)
Throws std::underflow_error if condition holds.
Definition ah-errors.H:373
#define ah_overflow_error_if(C)
Throws std::overflow_error if condition holds.
Definition ah-errors.H:468
@ 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.
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.
T & push(const T &data) noexcept(std::is_nothrow_copy_assignable_v< T >)
Push a copy of data
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
Generic heap of nodes.
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
Updates the priority of a node contained in the 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()
Removes the node with the lowest priority from the heap.
static bool is_in_list(Node *p) noexcept
Node * getRoot() const noexcept
Node * remove(Node *node)
Removes node from the heap.
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
Deletes all the nodes of the heap, invokes the destructors of the removed nodes, and frees all the 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
Inserts a node into a heap.
Node * top()
Returns the node with the lowest priority according to the comparison criterion specified in the decl...
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
Strict weak ordering constraint for BST comparators.
size_t blossom_maximum_cardinality_matching(const GT &g, DynDlist< typename GT::Arc * > &matching, SA sa=SA())
Alias of compute_maximum_cardinality_general_matching().
Definition Blossom.H:466
#define DECLARE_BINNODE(Name, height, Control_Data)
Specify tree node for a binary tree.
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
and
Check uniqueness with explicit hash + equality functors.
Heap of nodes with virtual destroyer.
Node heap without virtual destructor.
#define RLINK(i, n)
#define LLINK(i, n)
gsl_rng * r
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