Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

Loading...
Searching...
No Matches
MaxSequencePQTree.h
Go to the documentation of this file.
1
35#pragma once
36
37#include <ogdf/basic/Graph.h>
38#include <ogdf/basic/PQTree.h>
40
41#include <string.h>
42
43namespace ogdf {
44
96template<class T, class Y>
97class MaxSequencePQTree : public PQTree<T, whaInfo*, Y> {
98public:
99 using PQTree<T, whaInfo*, Y>::emptyNode;
100
102
104 while (!eliminatedNodes.empty()) {
107 delete nodePtr;
108 }
109 }
110
118
120
128
130
175
203
204protected:
205 using PQTree<T, whaInfo*, Y>::fullChildren;
206 using PQTree<T, whaInfo*, Y>::partialChildren;
207
223
245
253
262
263private:
287
299
314
329
332
339
359
366
377
383};
384
385template<class T, class Y>
387 // Queue for storing all pertinent nodes that still have
388 // to be processed.
390
391 /*
392 Enter the [[Full]] leaves into the queue [[processNodes]].
393 In a first step the pertinent leaves have to be identified in the tree
394 and entered on to the queue [[processNodes]]. The identification of
395 the leaves can be done with the help of a pointer stored in every
396 [[PQLeafKey]] (see \ref{PQLeafKey}) in constant time for every element.
397 */
399 for (it = leafKeys.begin(); it.valid(); ++it) {
400 PQNode<T, whaInfo*, Y>* checkLeaf = (*it)->nodePointer();
401 processNodes.append(checkLeaf);
402 cleanUp.pushBack(checkLeaf);
403 if (!checkLeaf->getNodeInfo()) { // if leaf does not have an information class for storing the [wha]-number allocate one.
404 whaInfo* newInfo = new whaInfo;
406 checkLeaf->setNodeInfo(infoPtr);
407 infoPtr->setNodePointer(checkLeaf);
408 }
409 checkLeaf->getNodeInfo()->userStructInfo()->m_notVisitedCount = 1;
411 }
412
413 /*
414 For every node in [[processNodes]], its father is detected using the
415 function [[GetParent]] \ref{GetParent}. The father is placed onto the
416 queue as well, if [[_nodePtr]] is its first child, that is popped from
417 the queue. In that case, the father is marked as [[Queued]] to
418 prevent the node from queue more than once. In any case, the number
419 of pertinent children of the father is updated. This is an important
420 number for computing the maximal pertinent sequence.
421 */
422 while (!processNodes.empty()) {
424 nodePtr->parent(GetParent(nodePtr));
425 if (nodePtr->parent() && !nodePtr->parent()->getNodeInfo())
426 // if the parent does not have an information
427 // class for storing the [wha]-number
428 // allocate one.
429 {
430 whaInfo* newInfo = new whaInfo;
432 nodePtr->parent()->setNodeInfo(infoPtr);
433 infoPtr->setNodePointer(nodePtr->parent());
434 }
435 if (nodePtr != this->m_root) {
436 if (nodePtr->parent()->mark() == PQNodeRoot::PQNodeMark::Unmarked) {
437 processNodes.append(nodePtr->parent());
438 cleanUp.pushBack(nodePtr->parent());
440 }
441 nodePtr->parent()->getNodeInfo()->userStructInfo()->m_notVisitedCount++;
442 int childCount = nodePtr->parent()->pertChildCount();
443 nodePtr->parent()->pertChildCount(++childCount);
444 }
445 }
446
447
448 /*
449 This chunk belongs to the function [[Bubble]]. After doing some
450 cleaning up and resetting the flags that have been left at the
451 pertinent nodes during the first bubble up, this chunk computes the
452 maximal pertinent sequence by calling the function [[determineMinRemoveSequence]].
453 It then removes
454 all leaves from the tree that have been marked as [[Eliminated]] and
455 possibly some internal nodes of the $PQ$-tree and stores pointers of
456 type [[leafKey]] for the pertinent leaves in the maximal sequence in the
457 array [[survivedElements]].
458 */
459
461 for (itn = cleanUp.begin(); itn.valid(); ++itn) {
463 }
464
465 return true;
466}
467
468template<class T, class Y>
470 if (nodePtr->getNodeInfo()) {
471 delete nodePtr->getNodeInfo()->userStructInfo();
472 delete nodePtr->getNodeInfo();
473 }
474}
475
476template<class T, class Y>
479 emptyNode(nodePtr);
481 } else if (nodePtr->status() == PQNodeRoot::PQNodeStatus::PertRoot) {
482 emptyNode(nodePtr);
483 } else {
484 // Node has an invalid status?
486 emptyNode(nodePtr);
487 }
488}
489
490template<class T, class Y>
493
494 while (!cleanUp.empty()) {
495 nodePtr = cleanUp.popFrontRet();
496 nodePtr->pertChildCount(0);
499 CleanNode(nodePtr);
500 delete nodePtr;
501 }
502
503 else {
504 // node must have an Information if contained in cleanUp
505 OGDF_ASSERT(nodePtr->getNodeInfo() != nullptr);
506
507 nodePtr->getNodeInfo()->userStructInfo()->m_notVisitedCount = 0;
508 nodePtr->getNodeInfo()->userStructInfo()->m_pertLeafCount = 0;
509 }
510 }
511
513 for (it = this->m_pertinentNodes->begin(); it.valid(); ++it) {
514 nodePtr = *it;
517 eliminatedNodes.pushBack(nodePtr);
518 } else if (nodePtr->status() == PQNodeRoot::PQNodeStatus::Full) {
520 } else if (nodePtr->status() == PQNodeRoot::PQNodeStatus::WhaDelete) {
522 } else if (nodePtr->getNodeInfo()) {
523 nodePtr->getNodeInfo()->userStructInfo()->defaultValues();
524 }
525 }
527}
528
529template<class T, class Y>
533 PQNode<T, whaInfo*, Y>* nodePtr = nullptr; // dummy
534
535 //Number of leaves that have to be deleted
536 int countDeletedLeaves = 0;
537 //Number of pertinent leaves
538 int maxPertLeafCount = 0;
539
540 // A queue storing the nodes whose $[w,h,a]$-number has to be computed next.
541 // A node is stored in [[processNodes]], if for all of its children the
542 // [w,h,a]-number has been computed.
544
545 // A stack storing all nodes where a $[w,h,a]$-number
546 // has been computed. This is necessary for a valid cleanup.
548
549 // Compute a valid parent pointer for every pertinent node.
550 Bubble(leafKeys);
551
552 // Get all pertinent leaves and stores them on [[processNodes]]
553 // and [[_archiv]].
555 for (it = leafKeys.begin(); it.valid(); ++it) {
556 PQNode<T, whaInfo*, Y>* checkLeaf = (*it)->nodePointer();
557 checkLeaf->getNodeInfo()->userStructInfo()->m_pertLeafCount = 1;
558 checkLeaf->getNodeInfo()->userStructInfo()->m_notVisitedCount--;
559 processNodes.append(checkLeaf);
560 archiv.push(checkLeaf);
561
563 }
564
565 while (!processNodes.empty()) {
566 nodePtr = processNodes.pop();
567 // Compute the $[w,h,a]$ number of [[nodePtr]]. Computing this number is
568 // trivial for leaves and full nodes. When considering a partial node, the
569 // computation has to distinguish between $P$- and $Q$-nodes.
570 if (nodePtr->getNodeInfo()->userStructInfo()->m_pertLeafCount < maxPertLeafCount) {
571 // In case that the actual node, depicted by the pointer
572 // [[nodePtr]] is not the root, the counts of the pertinent
573 // children of [[nodePtr]]'s parent are
574 // updated. In case that all pertinent children of the parent of
575 // [[nodePtr]] have a valid $[w,h,a]$-number, it is possible to compute
576 // the $[w,h,a]$-number of parent. Hence the parent is placed onto
577 // [[processNodes]]and [[_archiv]].
578 nodePtr->parent()->getNodeInfo()->userStructInfo()->m_pertLeafCount =
579 nodePtr->parent()->getNodeInfo()->userStructInfo()->m_pertLeafCount
580 + nodePtr->getNodeInfo()->userStructInfo()->m_pertLeafCount;
581 nodePtr->parent()->getNodeInfo()->userStructInfo()->m_notVisitedCount--;
582 if (!nodePtr->parent()->getNodeInfo()->userStructInfo()->m_notVisitedCount) {
583 processNodes.append(nodePtr->parent());
584 archiv.push(nodePtr->parent());
585 }
586 }
587 if (nodePtr->type() == PQNodeRoot::PQNodeType::Leaf) {
588 // Compute the $[w,h,a]$-number of a leaf. The computation is trivial.
590 nodePtr->getNodeInfo()->userStructInfo()->m_w = 1;
591 nodePtr->getNodeInfo()->userStructInfo()->m_h = 0;
592 nodePtr->getNodeInfo()->userStructInfo()->m_a = 0;
593 if (nodePtr->getNodeInfo()->userStructInfo()->m_pertLeafCount < maxPertLeafCount) {
594 fullChildren(nodePtr->parent())->pushFront(nodePtr);
595 }
596 } else {
597 // [[nodePtr]] is a $P$- or $Q$-node
598 // The $[w,h,a]$ number of $P$- or $Q$-nodes is computed identically.
599 // This is done calling the function [[sumPertChild]].
600 nodePtr->getNodeInfo()->userStructInfo()->m_w = sumPertChild(nodePtr);
601
602 if (fullChildren(nodePtr)->size() == nodePtr->childCount()) {
603 // computes the $h$- and $a$-numbers of a full node. The computation
604 // is trivial. It also updates the list of full nodes of the parent
605 // of [[nodePtr]].
607 if (nodePtr->getNodeInfo()->userStructInfo()->m_pertLeafCount < maxPertLeafCount) {
608 fullChildren(nodePtr->parent())->pushFront(nodePtr);
609 }
610 nodePtr->getNodeInfo()->userStructInfo()->m_h = 0;
611 nodePtr->getNodeInfo()->userStructInfo()->m_a = 0;
612 } else {
613 // computes the $[w,h,a]$-number of a partial node. The computation is
614 // nontrivial for both $P$- and $Q$-nodes and is performed in the
615 // function [[haNumPnode]] for $P$-nodes and in the
616 // function [[haNumQnode]] for $Q$-nodes.
617 // This chunk also updates the partial children stack of the parent.
619 if (nodePtr->getNodeInfo()->userStructInfo()->m_pertLeafCount < maxPertLeafCount) {
620 partialChildren(nodePtr->parent())->pushFront(nodePtr);
621 }
622
623 if (nodePtr->type() == PQNodeRoot::PQNodeType::PNode) {
624 haNumPnode(nodePtr);
625 } else {
626 haNumQnode(nodePtr);
627 }
628 }
629 }
630 }
631
632 // Determine the root of the pertinent subtree, which the last processed node
633 //[[nodePtr]] and finds the minimum of the $h$- and $a$-number of
634 //[[m_pertinentRoot]]. In case that the minimum is equal to $0$, the
635 //[[m_pertinentRoot]] stays of type $B$. Otherwise the type is selected
636 //according to the minimum.
637 OGDF_ASSERT(nodePtr != nullptr);
638 this->m_pertinentRoot = nodePtr;
639 if (this->m_pertinentRoot->getNodeInfo()->userStructInfo()->m_h
640 < this->m_pertinentRoot->getNodeInfo()->userStructInfo()->m_a) {
641 countDeletedLeaves = this->m_pertinentRoot->getNodeInfo()->userStructInfo()->m_h;
642 } else {
643 countDeletedLeaves = this->m_pertinentRoot->getNodeInfo()->userStructInfo()->m_a;
644 }
645
646 if (countDeletedLeaves > 0) {
647 if (this->m_pertinentRoot->getNodeInfo()->userStructInfo()->m_h
648 < this->m_pertinentRoot->getNodeInfo()->userStructInfo()->m_a) {
649 this->m_pertinentRoot->getNodeInfo()->userStructInfo()->m_deleteType = whaType::H;
650 } else {
651 this->m_pertinentRoot->getNodeInfo()->userStructInfo()->m_deleteType = whaType::A;
652 }
653 }
654
655 findMinWHASequence(archiv, eliminatedKeys);
656
657 return countDeletedLeaves;
658}
659
660template<class T, class Y>
663 //a pointer to the first child of type $h$ of [[nodePtr]].
665
666 //a pointer to the second child of type $h$ of [[nodePtr]].
668
669 //a pointer to the child of type $a$ of [[nodePtr]].
671
672 // pertinent sibling of hChild1
674
675 while (!archiv.empty()) {
676 //counts the number of children of [[nodePtr]].
677 int childCount = 0;
678
679 //a pointer to a pertinent node of the $PQ$-tree that is currently examined.
681
682 /*
683 Check if [[nodePtr]] is a full node whose delete type is either of
684 type $h$ or type $a$. Since there are no empty leaves in its
685 frontier, the node must therefore keep all its pertinent leaves
686 in its frontier and is depicted to be of type $b$.
687 */
689 && (nodePtr->getNodeInfo()->userStructInfo()->m_deleteType == whaType::H
690 || nodePtr->getNodeInfo()->userStructInfo()->m_deleteType == whaType::A)) {
691 nodePtr->getNodeInfo()->userStructInfo()->m_deleteType = whaType::B;
692 this->m_pertinentNodes->pushFront(nodePtr);
693 }
694
695 /*
696 Check if [[nodePtr]] is a leaf whose delete type is either of type $w$ or
697 $b$. In case it is of type $w$, the leaf has to be removed from the
698 tree to gain reducibility of the set $S$.
699 */
700 else if (nodePtr->type() == PQNodeRoot::PQNodeType::Leaf) {
701 if (nodePtr->getNodeInfo()->userStructInfo()->m_deleteType == whaType::W) {
702 eliminatedKeys.pushBack(nodePtr->getKey());
703 } else {
704 this->m_pertinentNodes->pushFront(nodePtr);
705 }
706 }
707
708 /*
709 Manage the case of [[nodePtr]] being either a partial $P$-node, a partial
710 $Q$-node, or a full $P$- or $Q$-node, where in the latter case the
711 delete type of [[nodePtr]] is of type $b$.
712 */
713 else {
714 switch (nodePtr->getNodeInfo()->userStructInfo()->m_deleteType) {
715 case whaType::B:
716 this->m_pertinentNodes->pushFront(nodePtr);
717 break;
718
719 case whaType::W:
721 nodePtr->pertChildCount(0);
722 this->m_pertinentNodes->pushFront(nodePtr);
723 break;
724
725 case whaType::H:
726 if (nodePtr->type() == PQNodeRoot::PQNodeType::PNode) {
727 /*
728 [[nodePtr]] is a $P$-node of type $h$. Mark all full
729 children of [[nodePtr]] to be of type $b$ (by doing nothing, since
730 the default is type $b$). It furthermore marks all partial children to
731 be of type $w$ except for the child stored in [[hChild1]] of the
732 information class of type [[whaInfo*]] of [[nodePtr]]. This child is
733 marked to be of type $h$.
734 */
736 markPertinentChildren(nodePtr, PQNodeRoot::PQNodeStatus::Full, whaType::B);
737 if (nodePtr->getNodeInfo()->userStructInfo()->m_hChild1) {
738 hChild1 =
739 (PQNode<T, whaInfo*, Y>*)nodePtr->getNodeInfo()->userStructInfo()->m_hChild1;
740 hChild1->getNodeInfo()->userStructInfo()->m_deleteType = whaType::H;
741 if (hChild1->getNodeInfo()->userStructInfo()->m_h
742 < hChild1->getNodeInfo()->userStructInfo()->m_w) {
743 childCount = 1;
744 }
745 }
746 nodePtr->pertChildCount(nodePtr->pertChildCount() + childCount
747 - partialChildren(nodePtr)->size());
748 } else {
749 /*
750 [[nodePtr]] is a $Q$-node. Mark all pertinent children
751 to be of type $w$, except for the full children between the
752 [[hChild1]] and the endmost child of [[nodePtr]]. These full
753 children are marked $b$ while [[hChild1]] is marked to be of type
754 $h$. Setting the type of children to $b$ or $h$ is hidden in the
755 function call [[setHchild]] \label{setHChild}.
756 */
758 hChild1 =
759 (PQNode<T, whaInfo*, Y>*)nodePtr->getNodeInfo()->userStructInfo()->m_hChild1;
760 nodePtr->pertChildCount(setHchild(hChild1));
761 }
762 this->m_pertinentNodes->pushFront(nodePtr);
763 break;
764
765 case whaType::A:
766 if (nodePtr->type() == PQNodeRoot::PQNodeType::PNode) {
767 /*
768 [[nodePtr]] is a $P$-node of type $a$.
769 Distinguish two main cases, based on the existence of a
770 child of [[nodePtr]] stored in [[aChild]] of the information
771 class of type [[_whaInfo]] of [[nodePtr]].
772 \begin{enumerate}
773 \item
774 If [[aChild]] is not empty, the chunk marks all full
775 and partial children of [[nodePtr]] to be of type $w$ and
776 marks the child [[aChild]] to be of type $a$.
777 \item
778 If [[aChild]] is empty, the chunk
779 marks all full children of [[nodePtr]] to be of type $b$
780 (by doing nothing, since the default is type $b$).
781 It furthermore marks all partial children to be of type $w$
782 except for the children stored in [[hChild1]] and
783 [[hChild2]] of the information class of type [[whaInfo*]] of
784 [[nodePtr]] which are marked to be of type $h$. Observe that
785 we have to distinguish the cases where both, [[_hChild]] and
786 [[hChild2]] are available, just [[_h_Child1]] is available or
787 none of the nodes exist.
788 \end{enumerate}
789 */
790 if (nodePtr->getNodeInfo()->userStructInfo()->m_aChild) {
791 markPertinentChildren(nodePtr, PQNodeRoot::PQNodeStatus::Pertinent,
792 whaType::W);
793 aChild = (PQNode<T, whaInfo*, Y>*)nodePtr->getNodeInfo()->userStructInfo()->m_aChild;
794 aChild->getNodeInfo()->userStructInfo()->m_deleteType = whaType::A;
795 nodePtr->pertChildCount(1);
796 } else {
797 markPertinentChildren(nodePtr, PQNodeRoot::PQNodeStatus::Full, whaType::B);
799 if (nodePtr->getNodeInfo()->userStructInfo()->m_hChild1) {
800 hChild1 = (PQNode<T, whaInfo*, Y>*)nodePtr->getNodeInfo()
801 ->userStructInfo()
802 ->m_hChild1;
803 hChild1->getNodeInfo()->userStructInfo()->m_deleteType = whaType::H;
804 if (hChild1->getNodeInfo()->userStructInfo()->m_h
805 < hChild1->getNodeInfo()->userStructInfo()->m_w) {
806 childCount = 1;
807 }
808 }
809 if (nodePtr->getNodeInfo()->userStructInfo()->m_hChild2) {
810 hChild2 = (PQNode<T, whaInfo*, Y>*)nodePtr->getNodeInfo()
811 ->userStructInfo()
812 ->m_hChild2;
813 hChild2->getNodeInfo()->userStructInfo()->m_deleteType = whaType::H;
814 if (hChild2->getNodeInfo()->userStructInfo()->m_h
815 < hChild2->getNodeInfo()->userStructInfo()->m_w) {
816 childCount++;
817 }
818 }
819 nodePtr->pertChildCount(nodePtr->pertChildCount() + childCount
820 - partialChildren(nodePtr)->size());
821 }
822 } else {
823 /*
824 [[nodePtr]] is a $Q$-node of type $a$.
825 Distinguish two main cases, based on the existence of a child of
826 [[nodePtr]] stored in [[aChild]] of the information class of type
827 [[_whaInfo]] of [[nodePtr]].
828 \begin{enumerate}
829 \item
830 If [[aChild]] is not empty, the chunk marks all full
831 and partial children of [[nodePtr]] to be of type $w$ and marks the
832 child [[aChild]] to be of type $a$.
833 \item
834 If [[aChild]] is empty, the chunk
835 marks all full and partial children of [[nodePtr]] to be of type $w$
836 except for the ones in the largest consecutive sequence of pertinent
837 children. This sequence
838 is depicted by the children [[hChild1]] and [[hChild2]] which may be
839 either full or partial. The children between [[hChild1]] and
840 [[hChild2]] are full and are marked $b$, while [[hChild1]] and
841 [[hChild2]] are marked $b$ or $h$, according to their status.
842 Setting the type of the nodes is hidden in calling the function
843 [[setAchildren]] (see \ref{setAchildren}).
844 \end{enumerate}
845 */
846 if (nodePtr->getNodeInfo()->userStructInfo()->m_aChild) {
847 aChild = (PQNode<T, whaInfo*, Y>*)nodePtr->getNodeInfo()->userStructInfo()->m_aChild;
848 markPertinentChildren(nodePtr, PQNodeRoot::PQNodeStatus::Pertinent,
849 whaType::W);
850 aChild->getNodeInfo()->userStructInfo()->m_deleteType = whaType::A;
851 nodePtr->pertChildCount(1);
852 } else {
853 markPertinentChildren(nodePtr, PQNodeRoot::PQNodeStatus::Pertinent,
854 whaType::W);
855 hChild2 =
856 (PQNode<T, whaInfo*, Y>*)nodePtr->getNodeInfo()->userStructInfo()->m_hChild2;
857 hChild2Sib = (PQNode<T, whaInfo*, Y>*)nodePtr->getNodeInfo()
858 ->userStructInfo()
859 ->m_hChild2Sib;
860 nodePtr->pertChildCount(setAchildren(hChild2, hChild2Sib));
861 }
862 }
863 this->m_pertinentNodes->pushFront(nodePtr);
864 break;
865 }
866 }
867
868 /*
869 After successfully determining the type of the children of [[nodePtr]],
870 this chunk cleans up the information needed during the
871 computation at the [[nodePtr]].
872 */
873 fullChildren(nodePtr)->clear();
874 partialChildren(nodePtr)->clear();
876 nodePtr->getNodeInfo()->userStructInfo()->m_hChild1 = nullptr;
877 nodePtr->getNodeInfo()->userStructInfo()->m_hChild2 = nullptr;
878 nodePtr->getNodeInfo()->userStructInfo()->m_aChild = nullptr;
879 nodePtr->getNodeInfo()->userStructInfo()->m_w = 0;
880 nodePtr->getNodeInfo()->userStructInfo()->m_h = 0;
881 nodePtr->getNodeInfo()->userStructInfo()->m_a = 0;
882 nodePtr->getNodeInfo()->userStructInfo()->m_deleteType = whaType::B;
883 }
884}
885
886template<class T, class Y>
888 // counts the number of pertinent children corresponding to the $[w,h,a]$-numbering.
889 int pertinentChildCount = 0;
890
891 // is [[true]] as long as children with a full label are found, [[false]] otherwise.
892 bool fullLabel = false;
893
895 PQNode<T, whaInfo*, Y>* nextSibling = nullptr; // dummy
896 PQNode<T, whaInfo*, Y>* oldSibling = nullptr; // dummy
897
898 if (hChild1 != nullptr) {
899 fullLabel = true;
900 }
901
902 /*
903 Trace the sequence of full children with at most one incident
904 pertinent child. It marks all full nodes as $b$-node and the partial
905 child, if available as $h$-child. The beginning of the sequence is
906 stored in [[currentNode]] which is equal to [[h_child1]] before
907 entering the while loop. Observe that this chunk cases if the while
908 loop while scanning the sequence has reached the second endmost child
909 of the $Q$-node (see [[if (nextSibling == 0)]]). This case may
910 appear, if all children of the $Q$-node are pertinent and the second
911 endmost child is the only partial child. The value [[fullLabel]] is
912 set to [[false]] as soon as the end of the sequence is detected.
913 */
914 while (fullLabel) {
915 nextSibling = currentNode->getNextSib(oldSibling);
916 if (!nextSibling) {
917 fullLabel = false;
918 }
919
921 currentNode->getNodeInfo()->userStructInfo()->m_deleteType = whaType::B;
923 }
924
925 else {
927 currentNode->getNodeInfo()->userStructInfo()->m_deleteType = whaType::H;
928 if ((currentNode->getNodeInfo()->userStructInfo()->m_pertLeafCount
929 - currentNode->getNodeInfo()->userStructInfo()->m_h)
930 > 0) {
932 }
933 }
934 fullLabel = false;
935 }
938 }
939
940 return pertinentChildCount;
941}
942
943template<class T, class Y>
946 /* Variables:
947 * - \a pertinentChildCount
948 * - \a reachedEnd
949 * - \a _sum denotes the number of pertinent leaves in the frontier
950 * of the sequence.
951 * - \a currentNode is the currently examined node of the sequence.
952 * - \a nextSibling is a pointer needed for tracing the sequence.
953 * - \a oldSibling is a pointer needed for tracing the sequence.
954 */
955 // counts the pertinent children of the sequence.
956 int pertinentChildCount = 0;
957
959 PQNode<T, whaInfo*, Y>* nextSibling = nullptr; // dummy
960 PQNode<T, whaInfo*, Y>* oldSibling = nullptr; // dummy
961
962 //Mark [[hChild2]] either as $b$- or as $h$-node.
963 if (hChild2->status() == PQNodeRoot::PQNodeStatus::Full) {
964 hChild2->getNodeInfo()->userStructInfo()->m_deleteType = whaType::B;
965 } else {
966 //1. node of sequence is Empty?
968 hChild2->getNodeInfo()->userStructInfo()->m_deleteType = whaType::H;
969 }
970
971 if (currentNode->getNodeInfo()->userStructInfo()->m_w
972 - currentNode->getNodeInfo()->userStructInfo()->m_h
973 > 0) {
975 }
976
977 //Trace the sequence of pertinent children, marking the full children as $b$-node.
978 //If a partial or empty node is detected, the end of the sequence is
979 //reached and the partial node is marked as $h$-node.
982
983 if (nextSibling != nullptr) {
985
986 // is false]as long as the end of the sequence is not detected; true otherwise.
987 bool reachedEnd = false;
988
989 while (!reachedEnd) {
991 currentNode->getNodeInfo()->userStructInfo()->m_deleteType = whaType::B;
993 } else {
995 currentNode->getNodeInfo()->userStructInfo()->m_deleteType = whaType::H;
996 if ((currentNode->getNodeInfo()->userStructInfo()->m_w
997 - currentNode->getNodeInfo()->userStructInfo()->m_h)
998 > 0) {
1000 }
1001 }
1002 reachedEnd = true;
1003 }
1004 if (!reachedEnd) {
1005 nextSibling = currentNode->getNextSib(oldSibling);
1006 if (nextSibling == nullptr) {
1007 reachedEnd = true;
1008 }
1011 }
1012 }
1013 }
1014
1015 return pertinentChildCount;
1016}
1017
1018template<class T, class Y>
1025#if 0
1027#endif
1028
1031 for (it = partialChildren(nodePtr)->begin(); it.valid(); ++it) {
1032 (*it)->getNodeInfo()->userStructInfo()->m_deleteType = deleteType;
1033 }
1034 for (it = fullChildren(nodePtr)->begin(); it.valid(); ++it) {
1035 (*it)->getNodeInfo()->userStructInfo()->m_deleteType = deleteType;
1036 }
1037 } else if (label == PQNodeRoot::PQNodeStatus::Partial) {
1039 for (it = partialChildren(nodePtr)->begin(); it.valid(); ++it) {
1040 (*it)->getNodeInfo()->userStructInfo()->m_deleteType = deleteType;
1041 }
1042 }
1043
1044 else {
1046 for (it = fullChildren(nodePtr)->begin(); it.valid(); ++it) {
1047 (*it)->getNodeInfo()->userStructInfo()->m_deleteType = deleteType;
1048 }
1049 }
1050}
1051
1052template<class T, class Y>
1054 /* Variables:
1055 * - \a sumParW = sum_{i in Par(\p nodePtr)} w_i, where
1056 * Par(\p nodePtr) denotes the set of partial children of \p nodePtr.
1057 * - \a sumMax1 = max_{i in Par(\p nodePtr)}1 {(w_i - h_i)}
1058 * where Par(\p nodePtr) denotes the set of partial children of
1059 * - \p nodePtr and max 1 the first maximum.
1060 * - \a sumMax2 = max_{i in Par(\p nodePtr)}2 {(w_i - h_i)}
1061 * where Par(\p nodePtr) denotes the set of partial children of
1062 * \p nodePtr and max2 the second maximum.
1063 * - \a currentNode
1064 * - \a hChild1 is a pointer to the \a hChild1 of \p nodePtr.
1065 * - \a hChild2 is a pointer to the \a hChild2 of \p nodePtr.
1066 * - \a aChild is a pointer to the \a aChild of \p nodePtr.
1067 */
1068 int sumParW = 0;
1069 int sumMax1 = 0;
1070 int sumMax2 = 0;
1074 PQNode<T, whaInfo*, Y>* aChild = nullptr;
1075
1076 /*
1077 Computes the $h$-number
1078 \[ h = \sum_{i \in Par(\mbox{[[nodePtr]]})}w_i - \max_{i\in
1079 Par(\mbox{[[nodePtr]]})}1\left\{(w_i - h_i)\right\}\]
1080 of the $P$-node [[nodePtr]].
1081 This is done by scanning all partial children stored in the
1082 [[partialChildrenStack]] of [[nodePtr]] summing up the $w_i$ for every
1083 $i \in Par(\mbox{[[nodePtr]]})$ and detecting
1084 \[\max_{i\in Par(\mbox{[[nodePtr]]})}1\left\{(w_i - h_i)\right\}.\]
1085 Since this can be simultaneously it also computes
1086 \[\max_{i\in Par(\mbox{[[nodePtr]]})}2\left\{(w_i - h_i)\right\}\]
1087 which is needed to determine the $a$-number.
1088 After successfully determining the $h$-number, the [[hChild1]] and
1089 [[hChild2]] of [[nodePtr]] are set.
1090 */
1091
1093 for (it = partialChildren(nodePtr)->begin(); it.valid(); ++it) {
1094 currentNode = (*it);
1095 sumParW = sumParW + currentNode->getNodeInfo()->userStructInfo()->m_w;
1096 int sumHelp = currentNode->getNodeInfo()->userStructInfo()->m_w
1097 - currentNode->getNodeInfo()->userStructInfo()->m_h;
1098 if (sumMax1 <= sumHelp) {
1099 sumMax2 = sumMax1;
1100 hChild2 = hChild1;
1101 sumMax1 = sumHelp;
1103 } else if (sumMax2 <= sumHelp) {
1104 sumMax2 = sumHelp;
1106 }
1107 }
1108 nodePtr->getNodeInfo()->userStructInfo()->m_hChild1 = hChild1;
1109 nodePtr->getNodeInfo()->userStructInfo()->m_hChild2 = hChild2;
1110 nodePtr->getNodeInfo()->userStructInfo()->m_h = sumParW - sumMax1;
1111
1112 /*
1113 Compute the $a$-number of the $P$-node [[nodePtr]] where
1114 \[ a = \min \{ \alpha_1, \alpha_2\}\]
1115 such that
1116 \[\alpha_1 = \sum_{i \in P(\mbox{[[nodePtr]]})}w_i - \max_{i\in
1117 P(\mbox{[[nodePtr]]})}\left\{(w_i - h_i)\right\} \]
1118 which can be computed calling the function [[alpha1beta1Number]] and
1119 \[{\alpha}_2 \sum_{i \in Par(\mbox{[[nodePtr]]})}w_i -
1120 \max_{i\in Par(\mbox{[[nodePtr]]})}1\left\{(w_i - h_i)\right\}
1121 - \max_{i\in Par(\mbox{[[nodePtr]]})}2\left\{(w_i - h_i)\right\}\]
1122 This chunk uses two extra variables
1123 \begin{description}
1124 \item[[alpha1]] $ = \alpha_1$.
1125 \item[[alpha2]] $ = \alpha_2$.
1126 \end{description}
1127 */
1128 int alpha2 = sumParW - sumMax1 - sumMax2;
1129 int alpha1 = alpha1beta1Number(nodePtr, &aChild);
1130
1131 if (alpha1 <= alpha2) {
1132 nodePtr->getNodeInfo()->userStructInfo()->m_a = alpha1;
1133 nodePtr->getNodeInfo()->userStructInfo()->m_aChild = aChild;
1134 } else {
1135 nodePtr->getNodeInfo()->userStructInfo()->m_a = alpha2;
1136 nodePtr->getNodeInfo()->userStructInfo()->m_aChild = nullptr;
1137 }
1138}
1139
1140template<class T, class Y>
1142 /* Variables:
1143 * - sumAllW = sum_{i in P(\p nodePtr)} w_i, where
1144 * P(\p nodePtr) denotes the set of pertinent children of \p nodePtr.
1145 */
1146 int sumAllW = sumPertChild(nodePtr);
1147
1148 hNumQnode(nodePtr, sumAllW);
1149 aNumQnode(nodePtr, sumAllW);
1150}
1151
1152template<class T, class Y>
1154 /* Variables:
1155 * - \a sumLeft = sum_{i in P(\p nodePtr)} w_i - sum_{i
1156 * in P_L(\p nodePtr)}(w_i - h_i), where
1157 * P_L(\p nodePtr) denotes the maximal consecutive sequence
1158 * of pertinent children on the left side of the Q-node
1159 * \p nodePtr such that only the rightmost node in
1160 * P_L(\p nodePtr) may be partial.
1161 * - \a sumRight = sum_{i in P(\p [nodePtr)}w_i - sum_{i
1162 * in P_L(\p nodePtr)}(w_i - h_i), where
1163 * P_L(\p nodePtr) denotes the maximal consecutive sequence
1164 * of pertinent children on the left side of the Q-node
1165 * \p nodePtr such that only the rightmost node in
1166 * P_L(\p nodePtr) may be partial.
1167 * - \a fullLabel
1168 * - \a aChild is a pointer to the a-child of \p nodePtr.
1169 * - \a leftChild is a pointer to the left endmost child of \p nodePtr.
1170 * - \a rightChild is a pointer to the right endmost child of \p nodePtr.
1171 * - \a holdSibling is a pointer to a child of \p nodePtr, needed
1172 * to proceed through sequences of pertinent children.
1173 * - \a checkSibling is a pointer to a currently examined child of \p nodePtr.
1174 */
1175 int sumLeft = 0;
1176 int sumRight = 0;
1177 bool fullLabel = true;
1182
1183 //Compute the $h$-number of the $Q$-node [[nodePtr]]
1184
1185 //Get endmost children of the $Q$-node [[nodePtr]].
1186 leftChild = nodePtr->getEndmost(nullptr);
1187 rightChild = nodePtr->getEndmost(leftChild);
1190
1191 /*
1192 Check the left
1193 side of the $Q$-node [[nodePtr]] for the maximal consecutive sequence
1194 of full nodes, including at most one partial child at the end of the sequence.
1195
1196 The variable [[fullLabel]] is [[true]] as long as the [[while]]-loop
1197 has not detected an partial <b>or</b> empty child (see case [[if
1198 (leftChild->status() != Full)]]. Observe that the
1199 construction of the [[while]]-loop examines the last child if it is a
1200 partial child as well (see case [[if (leftChild->status() !=
1201 Empty)]] where in the computation in [[sumLeft]] we take advantage
1202 of the fact, that the $h$-number of a full child is zero).
1203 */
1204 while (fullLabel) {
1205 if (leftChild->status() != PQNodeRoot::PQNodeStatus::Full) {
1206 fullLabel = false;
1207 }
1208 if (leftChild->status() != PQNodeRoot::PQNodeStatus::Empty) {
1209 sumLeft = sumLeft + leftChild->getNodeInfo()->userStructInfo()->m_w
1210 - leftChild->getNodeInfo()->userStructInfo()->m_h;
1211 checkSibling = leftChild->getNextSib(holdSibling);
1212 if (checkSibling == nullptr) {
1213 fullLabel = false;
1214 }
1217 }
1218 }
1219
1220 /*
1221 Check the right
1222 side of the $Q$-node [[nodePtr]] for the maximal consecutive sequence
1223 of full nodes, including at most one partial child at the end of the sequence.
1224
1225 The variable [[fullLabel]] is [[true]] as long as the [[while]]-loop
1226 has not detected an partial <b>or</b> empty child (see case [[if
1227 (leftChild->status() != Full)]]. Observe that the
1228 construction of the [[while]]-loop examines the last child if it is a
1229 partial child as well (see case [[if (leftChild->status() !=
1230 Empty)]] where in the computation in [[sumLeft]] we take advantage
1231 of the fact, that the $h$-number of a full child is zero).
1232 */
1233 holdSibling = nullptr;
1234 checkSibling = nullptr;
1235 fullLabel = true;
1236 while (fullLabel) {
1237 if (rightChild->status() != PQNodeRoot::PQNodeStatus::Full) {
1238 fullLabel = false;
1239 }
1241 sumRight = sumRight + rightChild->getNodeInfo()->userStructInfo()->m_w
1242 - rightChild->getNodeInfo()->userStructInfo()->m_h;
1243
1244 checkSibling = rightChild->getNextSib(holdSibling);
1245
1246 if (checkSibling == nullptr) {
1247 fullLabel = false;
1248 }
1249
1252 }
1253 }
1254
1255 /*
1256 After computing the number of pertinent leaves that stay in the $PQ$-tree
1257 when keeping either the left pertinent or the right pertinent side of
1258 the $Q$-node in the tree, this chunk chooses the side where the
1259 maximum number of leaves stay in the tree.
1260 Observe that we have to case the fact, that on both sides of the
1261 $Q$-node [[nodePtr]] no pertinent children are.
1262 */
1263 leftChild = nodePtr->getEndmost(nullptr);
1264 rightChild = nodePtr->getEndmost(leftChild);
1265 if (sumLeft == 0 && sumRight == 0) {
1266 nodePtr->getNodeInfo()->userStructInfo()->m_h = sumAllW;
1267 nodePtr->getNodeInfo()->userStructInfo()->m_hChild1 = nullptr;
1268 } else if (sumLeft < sumRight) {
1269 nodePtr->getNodeInfo()->userStructInfo()->m_h = sumAllW - sumRight;
1270 nodePtr->getNodeInfo()->userStructInfo()->m_hChild1 = rightChild;
1271 } else {
1272 nodePtr->getNodeInfo()->userStructInfo()->m_h = sumAllW - sumLeft;
1273 nodePtr->getNodeInfo()->userStructInfo()->m_hChild1 = leftChild;
1274 }
1275}
1276
1277template<class T, class Y>
1279 /* Variables:
1280 * - \a beta1 = sum_{i in P(\p nodePtr} w_i - max_{i in P(\p nodePtr)}{(w_i =
1281 * a_i)}, where $P(\p nodePtr) denotes the set of all pertinent
1282 * children of the Q-node \p nodePtr. Depicts the a-number if just one
1283 * child of \p nodePtr is made a-node. Computed by calling the function alpha1beta1Number().
1284 * - \a beta2 = sum_{i in P(\p nodePtr)} w_i - max_{P_A(\p nodePtr)}{sum_{i in
1285 * P_A(\p nodePtr)}(w_i-h_i)}, where $P_A(\p nodePtr) is a maximal consecutive
1286 * sequence of pertinent children of the Q-node \p nodePtr such that all
1287 * nodes in P_A(\p nodePtr) except for the leftmost and rightmost ones are
1288 * full. Computed by this chunk.
1289 * - \a aSum depicts the number of pertinent leaves of the actual visited sequence.
1290 * - \a aHoldSum depicts the number of leaves in the actual maximum sequence.
1291 * - \a endReached is true if reached the end of the Q-node \p nodePtr and false otherwise.
1292 * - \a leftMost pointer to the leftmost end of the actual visited sequence.
1293 * - \a leftMostHold pointer to the leftmost end of the current maximum sequence.
1294 * - \a actualNode pointer to a child of the Q-node. It is the
1295 * node that is actually processed in the sequence of children.
1296 * - \a currentNode pointer to a node in a consecutive pertinent
1297 * sequence. Needed to process all nodes stored in \a sequence.
1298 * - \a lastChild is a pointer to the endmost child of the Q-node
1299 * that is opposite to the endmost child, where this chunk starts
1300 * processing the sequence of children.
1301 * - \a sequence is a SList of type PQNode<T,whaInfo*,Y>* storing
1302 * the nodes of a consecutive sequence that is actually processed.
1303 */
1304 PQNode<T, whaInfo*, Y>* aChild = nullptr;
1305 int beta1 = alpha1beta1Number(nodePtr, &aChild);
1306 int beta2 = 0;
1307 int aSum = 0;
1308 int aHoldSum = 0;
1309 bool endReached = 0;
1319 // pointer to the second endmost child
1320
1322
1323 actualNode = nodePtr->getEndmost(nullptr);
1324 lastChild = nodePtr->getEndmost(actualNode);
1325
1326 endReached = false;
1327 while (!endReached) {
1328 /*
1329 Process the children of a $Q$-node [[nodePtr]] from one end of [[nodePtr]] to the
1330 other, searching for a consecutive sequence of pertinent nodes with
1331 the maximum number of pertinent leaves, such that all nodes of the
1332 pertinent sequence are full except possibly the two endmost children
1333 which are allowed to be partial.
1334 */
1335 if (sequence.empty()) {
1336 /*
1337 Currently no consecutive sequence of pertinent children
1338 is detected while scanning the children of the $Q$-node.
1339 Check the [[actualNode]] if it is the first child of
1340 such a sequence. If so, place [[actualNode]] on the stack [[sequence]].
1341 */
1343 sequence.pushFront(actualNode);
1344 leftMost = nullptr;
1345 leftSib = nullptr;
1346 }
1347 } else {
1348 /*
1349 [[actualNode]] is a sibling of a consecutive pertinent sequence that has
1350 been detected in an earlier step, while scanning the children of the $Q$-node.
1351 This chunk cases on the status of the [[actualNode]].
1352
1353 In case that the status of
1354 the [[actualNode]] is [[Full]], [[actualNode]] is included into the
1355 sequence of pertinent children by pushing it onto the stack
1356 [[sequence]].
1357
1358 If [[actualNode]] is Empty, we have reached the end of
1359 the actual consecutive sequence of pertinent children. In this case
1360 the $a$-numbers of the nodes in the sequence have to be summed up.
1361
1362 If the [[actualNode]] is [[Partial]], the end of the consecutive sequence
1363 is reached and similar actions to the [[Empty]] have to be
1364 performed. However, [[actualNode]] might mark the beginning of
1365 another pertinent sequence. Hence it has to be stored again in [[sequence]].
1366 */
1367 if (actualNode->status() == PQNodeRoot::PQNodeStatus::Full) {
1368 sequence.pushFront(actualNode);
1369 }
1370
1371 else if (actualNode->status() == PQNodeRoot::PQNodeStatus::Empty) {
1372 /*
1373 If [[actualNode]] is Empty, the end of
1374 the actual consecutive sequence of pertinent children is reached . In
1375 this case, all nodes of the currently examined consecutive sequence are stored in
1376 [[sequence]].
1377 They are removed from the stack and their $a$-numbers are summed up.
1378 If necessary, the sequence with the largest number of full leaves in
1379 its frontier is updated.
1380 */
1381 aSum = 0;
1382
1383 while (!sequence.empty()) {
1384 currentNode = sequence.popFrontRet();
1385 aSum = aSum + currentNode->getNodeInfo()->userStructInfo()->m_w
1386 - currentNode->getNodeInfo()->userStructInfo()->m_h;
1387 if (sequence.size() == 1) {
1389 }
1390 }
1392
1393 if (aHoldSum < aSum) {
1394 aHoldSum = aSum;
1397 }
1398
1399 } else {
1400 /*
1401 If the [[actualNode]] is [[Partial]], the end of the consecutive sequence
1402 is reached. In
1403 this case, all nodes of the currently examined consecutive sequence are stored in
1404 [[sequence]].
1405 They are removed from the stack and their $a$-numbers are summed up.
1406 If necessary, the sequence with the largest number of full leaves in
1407 its frontier is updated.
1408 However, [[actualNode]] might mark the beginning of
1409 another pertinent sequence. Hence it has to be stored again in [[sequence]].
1410 */
1411 sequence.pushFront(actualNode);
1412 aSum = 0;
1413 while (!sequence.empty()) {
1414 currentNode = sequence.popFrontRet();
1415 aSum = aSum + currentNode->getNodeInfo()->userStructInfo()->m_w
1416 - currentNode->getNodeInfo()->userStructInfo()->m_h;
1417 if (sequence.size() == 1) {
1419 }
1420 }
1421 if (leftSib == nullptr) {
1423 }
1425
1426 if (aHoldSum < aSum) {
1427 aHoldSum = aSum;
1430 }
1431
1432 sequence.pushFront(actualNode);
1433 }
1434 }
1435
1436 // Get the next sibling
1437 if (actualNode != lastChild) {
1438 checkSibling = actualNode->getNextSib(holdSibling);
1441 } else {
1442 // End of Q-node reached.
1443 endReached = true;
1444 }
1445 }
1446
1447
1448 /*
1449 After processing
1450 the last child of the $Q$-node, this chunk checks, if this child was
1451 part of a pertinent consecutive sequence. If this is the case, the
1452 stack storing this seuquence was not emptied and the number of
1453 pertinent leaves in its frontier was not computed. Furhtermore the
1454 last child was not stored in [[sequence]].
1455 This chunk does the necessary updates for the last consecutive sequence.
1456 */
1457 if (!sequence.empty()) {
1458 aSum = 0;
1459 while (!sequence.empty()) {
1460 currentNode = sequence.popFrontRet();
1461 aSum = aSum + currentNode->getNodeInfo()->userStructInfo()->m_w
1462 - currentNode->getNodeInfo()->userStructInfo()->m_h;
1463 if (sequence.size() == 1) {
1465 }
1466 }
1468
1469 if (aHoldSum < aSum) {
1470 aHoldSum = aSum;
1473 }
1474 }
1475 /*
1476 After computing
1477 ${\beta}_1$ and ${\beta}_2$, describing the number of pertinent leaves
1478 that have to be deleted when choosing either one node to be an
1479 $a$-node or a complete sequence, this chunk gets the $a$-number of the
1480 $Q$-node [[nodePtr]] by choosing
1481 \[a = \min\{{\beta}_1,{\beta}_2\]
1482 Also set [[aChild]] and [[hChild2]] of [[nodePtr]] according to the
1483 chosen minimum.
1484 */
1486 if (beta2 < beta1) {
1487 nodePtr->getNodeInfo()->userStructInfo()->m_a = beta2;
1488 nodePtr->getNodeInfo()->userStructInfo()->m_hChild2 = leftMostHold;
1489 nodePtr->getNodeInfo()->userStructInfo()->m_hChild2Sib = leftSibHold;
1490 nodePtr->getNodeInfo()->userStructInfo()->m_aChild = nullptr;
1491 } else {
1492 nodePtr->getNodeInfo()->userStructInfo()->m_a = beta1;
1493 nodePtr->getNodeInfo()->userStructInfo()->m_hChild2 = nullptr;
1494 nodePtr->getNodeInfo()->userStructInfo()->m_hChild2Sib = nullptr;
1495 nodePtr->getNodeInfo()->userStructInfo()->m_aChild = aChild;
1496 }
1497}
1498
1499template<class T, class Y>
1502 /* Variables:
1503 * - \a sumMaxA = max_{i in P(\p nodePtr)}{(w_i = a_i)}.
1504 * - \a sumAllW = w = sum_{i in P(\p nodePtr)}w_i.
1505 * - \a sumHelp is a help variable.
1506 * - \a currentNode depicts a currently examined pertinent node.
1507 *
1508 * The function uses two while loops over the parial and the full
1509 * children of \p nodePtr. It hereby computes the values \p w and
1510 * max_{i in P(\p nodePtr}{(w_i = a_i)}.
1511 * After finishing the while loops, the function
1512 * alpha1beta1Number() returns the numbers alpha_1 = beta_1
1513 * and the \p aChild.
1514 */
1515 int sumMaxA = 0;
1516 int sumAllW = 0;
1517 int sumHelp = 0;
1519
1521 for (it = fullChildren(nodePtr)->begin(); it.valid(); ++it) {
1522 currentNode = (*it);
1523 sumAllW = sumAllW + currentNode->getNodeInfo()->userStructInfo()->m_w;
1524 sumHelp = currentNode->getNodeInfo()->userStructInfo()->m_w
1525 - currentNode->getNodeInfo()->userStructInfo()->m_a;
1526 if (sumMaxA < sumHelp) {
1527 sumMaxA = sumHelp;
1528 (*aChild) = currentNode;
1529 }
1530 }
1531
1532 for (it = partialChildren(nodePtr)->begin(); it.valid(); ++it) {
1533 currentNode = (*it);
1534 sumAllW = sumAllW + currentNode->getNodeInfo()->userStructInfo()->m_w;
1535 sumHelp = currentNode->getNodeInfo()->userStructInfo()->m_w
1536 - currentNode->getNodeInfo()->userStructInfo()->m_a;
1537 if (sumMaxA < sumHelp) {
1538 sumMaxA = sumHelp;
1539 (*aChild) = currentNode;
1540 }
1541 }
1542 return sumAllW - sumMaxA;
1543}
1544
1545template<class T, class Y>
1547 /* Variables:
1548 * - \a it depicts a currently examined pertinent node.
1549 * - \a sum = \a w = sum_{i in P(\p nodePtr)}w_i.
1550 *
1551 * The function uses two for loops over the parial and the full
1552 * children of \p nodePtr. It hereby computes the values $w$ stored in \a sum.
1553 * After finishing the while loops, the function
1554 * sumPertChild() returns the number \a w.
1555 */
1556 int sum = 0;
1558 for (it = fullChildren(nodePtr)->begin(); it.valid(); ++it) {
1559 sum = sum + (*it)->getNodeInfo()->userStructInfo()->m_w;
1560 }
1561 for (it = partialChildren(nodePtr)->begin(); it.valid(); ++it) {
1562 sum = sum + (*it)->getNodeInfo()->userStructInfo()->m_w;
1563 }
1564
1565 return sum;
1566}
1567
1568template<class T, class Y>
1570 if (nodePtr->parent() == nullptr) {
1571 return nullptr;
1572 } else if (nodePtr->parent()->status() != PQNodeRoot::PQNodeStatus::Eliminated) {
1573 return nodePtr->parent();
1574 } else {
1575 PQNode<T, whaInfo*, Y>* nextNode = nodePtr;
1577 PQNode<T, whaInfo*, Y>* oldSib = nullptr;
1579
1580 currentNode = nodePtr->getNextSib(nullptr);
1581 oldSib = nodePtr;
1582 L.pushFront(nodePtr);
1583 while (currentNode->parent()->status() == PQNodeRoot::PQNodeStatus::Eliminated) {
1584 L.pushFront(currentNode);
1585 nextNode = currentNode->getNextSib(oldSib);
1587 currentNode = nextNode;
1588 }
1589 while (!L.empty()) {
1590 L.popFrontRet()->parent(currentNode->parent());
1591 }
1592 return currentNode->parent();
1593 }
1594}
1595
1596}
Includes declaration of graph class.
Declaration and implementation of the class PQTree.
An array that keeps track of the number of inserted elements; also usable as an efficient stack.
Definition ArrayBuffer.h:56
Encapsulates a pointer to a list element.
Definition List.h:103
bool valid() const
Returns true iff the iterator points to an element.
Definition List.h:137
The class template MaxSequencePQTree is designed to compute a maximal consecutive sequence of pertine...
int determineMinRemoveSequence(SListPure< PQLeafKey< T, whaInfo *, Y > * > &leafKeys, SList< PQLeafKey< T, whaInfo *, Y > * > &eliminatedKeys)
Computes the maximal pertinent sequence S' of elements of the set S, that can be reduced in a PQ-tree...
void markPertinentChildren(PQNode< T, whaInfo *, Y > *nodePtr, PQNodeRoot::PQNodeStatus label, whaType deleteType)
Marks all full and/or partial children of nodePtr as either an a-, b-, h- or w-node.
PQNode< T, whaInfo *, Y > * GetParent(PQNode< T, whaInfo *, Y > *nodePtr)
Computes for the node nodePtr its valid parent in the PQ-tree.
void aNumQnode(PQNode< T, whaInfo *, Y > *nodePtr, int sumAllW)
Computes the a-number of the partial Q-node nodePtr.
void findMinWHASequence(ArrayBuffer< PQNode< T, whaInfo *, Y > * > &archiv, SList< PQLeafKey< T, whaInfo *, Y > * > &eliminatedKeys)
Checks the [w,h,a]-number of the pertinent root.
SListPure< PQNode< T, whaInfo *, Y > * > eliminatedNodes
Used to store all eliminated nodes (status == PQNodeRoot::PQNodeStatus::Eliminated) of the PQTree.
int alpha1beta1Number(PQNode< T, whaInfo *, Y > *nodePtr, PQNode< T, whaInfo *, Y > **aChild)
Returns alpha_1 = beta_1 = sum_{i in P(nodePtr)} w_i - max_{i in P(nodePtr)}{(w_i = a_i)},...
virtual void CleanNode(PQNode< T, whaInfo *, Y > *nodePtr)
Frees the memory allocated for the node information class of a node in the PQTree.
int sumPertChild(PQNode< T, whaInfo *, Y > *nodePtr)
Returns w = sum_{i in P(nodePtr)}w_i, where nodePtr is any pertinent node of the PQ-tree.
SListPure< PQNode< T, whaInfo *, Y > * > cleanUp
Used to store all pertinent Nodes of the pertinent subtree before removing the minimal pertinent subs...
void haNumQnode(PQNode< T, whaInfo *, Y > *nodePtr)
Computes the h- and a-number of the partial Q-node nodePtr.
virtual bool Bubble(SListPure< PQLeafKey< T, whaInfo *, Y > * > &leafKeys)
The function Bubble() is an overloaded function of the base template class PQTree.
int setAchildren(PQNode< T, whaInfo *, Y > *hChild2, PQNode< T, whaInfo *, Y > *hChild2Sib)
Traces all children of the largest consecutive sequence of pertinent children of a Q-node.
int setHchild(PQNode< T, whaInfo *, Y > *hChild1)
Processes the children of a Q-node, marking a full sequence of children with at most incident partial...
virtual void emptyAllPertinentNodes()
Does a clean up after a reduction.
void hNumQnode(PQNode< T, whaInfo *, Y > *nodePtr, int sumAllW)
Computes the h-number of the partial Q-node nodePtr.
void haNumPnode(PQNode< T, whaInfo *, Y > *nodePtr)
Computes the h- and a-number of a P-node nodePtr.
virtual void clientDefinedEmptyNode(PQNode< T, whaInfo *, Y > *nodePtr)
Does a clean up of a node. Called by emptyAllPertinentNodes.
The class template PQLeafKey is a derived class of class template PQBasicKey.
Definition PQLeafKey.h:87
The class template PQBasicKey is an abstract base class.
Definition PQNode.h:55
The class template PQNodeKey is a derived class of class template PQBasicKey.
Definition PQNodeKey.h:57
@ Eliminated
Nodes removed during the template reduction are marked as as Eliminated. Their memory is not freed....
@ WhaDelete
Nodes that need to be removed in order to obtain a maximal pertinent sequence are marked WhaDelete.
@ PertRoot
The pertinent Root is marked PertRoot during the clean up after a reduction. Technical.
List< PQNode< T, whaInfo *, Y > * > * partialChildren(PQNode< T, whaInfo *, Y > *nodePtr)
Definition PQTree.h:653
void emptyNode(PQNode< T, whaInfo *, Y > *nodePtr)
Cleans up all stacks, flags and pointers of a pertinent node that has been visited during the reducti...
Definition PQTree.h:1772
virtual void emptyAllPertinentNodes()
Cleans up all flags that have been set in the pertinent nodes during the reduction process.
Definition PQTree.h:1737
List< PQNode< T, whaInfo *, Y > * > * fullChildren(PQNode< T, whaInfo *, Y > *nodePtr)
Definition PQTree.h:651
The parameterized class Queue<E> implements list-based queues.
Definition Queue.h:200
Singly linked lists (maintaining the length of the list).
Definition SList.h:833
Encapsulates a pointer to an ogdf::SList element.
Definition SList.h:92
bool valid() const
Returns true iff the iterator points to an element.
Definition SList.h:122
Singly linked lists.
Definition SList.h:179
#define OGDF_ASSERT(expr)
Assert condition expr. See doc/build.md for more information.
Definition basic.h:41
static MultilevelBuilder * getDoubleFactoredZeroAdjustedMerger()
The namespace for all OGDF objects.
whaType
The definitions for W, B, H and A describe the type of a node during the computation of the maximal p...
Definition whaInfo.h:48
Declaration of class whaInfo.