Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

Loading...
Searching...
No Matches
PQTree.h
Go to the documentation of this file.
1
32#pragma once
33
34#include <ogdf/basic/Array.h>
36#include <ogdf/basic/List.h>
37#include <ogdf/basic/Queue.h>
38#include <ogdf/basic/SList.h>
39#include <ogdf/basic/basic.h>
40#include <ogdf/basic/internal/config_autogen.h>
43#include <ogdf/basic/pqtree/PQLeafKey.h> // IWYU pragma: keep
46
47#include <fstream>
48#include <utility>
49
50namespace ogdf {
51
52template<class T, class X, class Y>
53class PQTree {
54public:
56
66 virtual ~PQTree() { Cleanup(); }
67
84 SListPure<PQLeafKey<T, X, Y>*>& leafKeys);
85
90 void emptyNode(PQNode<T, X, Y>* nodePtr);
91
101 virtual void front(PQNode<T, X, Y>* nodePtr, SListPure<PQLeafKey<T, X, Y>*>& leafKeys);
102
103 virtual void CleanNode(PQNode<T, X, Y>* /* nodePtr */) { }
104
116 virtual void Cleanup();
117
124 virtual void clientDefinedEmptyNode(PQNode<T, X, Y>* nodePtr) { emptyNode(nodePtr); }
125
135
153 virtual int Initialize(SListPure<PQLeafKey<T, X, Y>*>& leafKeys);
154
166 virtual bool Reduction(SListPure<PQLeafKey<T, X, Y>*>& leafKeys);
167
169 PQNode<T, X, Y>* root() const { return m_root; }
170
173 void writeGML(const char* fileName);
174 void writeGML(std::ostream& os);
176
177protected:
180
183
186
188
193
196
206
215 virtual bool Bubble(SListPure<PQLeafKey<T, X, Y>*>& leafKeys);
216
245 virtual bool Reduce(SListPure<PQLeafKey<T, X, Y>*>& leafKeys);
246
267 virtual bool templateL1(PQNode<T, X, Y>* nodePtr, bool isRoot);
268
289 virtual bool templateP1(PQNode<T, X, Y>* nodePtr, bool isRoot);
290
310 virtual bool templateP2(PQNode<T, X, Y>** nodePtr);
311
335 virtual bool templateP3(PQNode<T, X, Y>* nodePtr);
336
361 virtual bool templateP4(PQNode<T, X, Y>** nodePtr);
362
378 virtual bool templateP5(PQNode<T, X, Y>* nodePtr);
379
403 virtual bool templateP6(PQNode<T, X, Y>** nodePtr);
404
430 virtual bool templateQ1(PQNode<T, X, Y>* nodePtr, bool isRoot);
431
461 virtual bool templateQ2(PQNode<T, X, Y>* nodePtr, bool isRoot);
462
463 /*
464 * Template matching for Q-nodes with empty and/or partial children at both
465 * ends and a sequence of full and/or partial children in the middle.
466 * The Q-node must be the root of the pertinent subtree.
467 * The function requires as input any pointer to a node stored in
468 * \p nodePtr. If the node stored in \p nodePtr is a Q-node
469 * with empty and/or partial children at both ends and a sequence
470 * full or partial children in the middle,
471 * templateQ3() considers itself responsible for the node and will
472 * apply the template matching \b Q3 to \p nodePtr.
473 * Observe that the user calling this function has to make sure that
474 * \p nodePtr is the root of the pertinent subtree.
475 *
476 * If templateQ3() was responsible for \p nodePtr and the
477 * reduction was successful, the return value is 1. Otherwise
478 * the return value is 0.
479 *
480 * Below a short description is given of all different cases that
481 * may occure and are handled by the function templateQ3(), \b regardless
482 * whether the Q-node \p nodePtr is the root of the pertinent subtree or not.
483 * The description is somewhat trunkated and should be understood as a
484 * stenographic description of the labels of the children of \p nodePtr
485 * when running through the children from one side to the other. Of course
486 * we leave the mirror-images out.
487 * - empty, full, empty
488 * - empty, partial, full, partial, empty
489 * - empty, partial, full, empty
490 * - empty, partial, full, partial
491 * - partial, full, partial
492 * - empty, partial, partial, empty
493 * - empty, partial, partial
494 * - partial, partial
495 */
496 virtual bool templateQ3(PQNode<T, X, Y>* nodePtr);
497
510
543 PQNode<T, X, Y>* leftBrother, PQNode<T, X, Y>* rightBrother);
544
560 virtual bool checkIfOnlyChild(PQNode<T, X, Y>* child, PQNode<T, X, Y>* parent);
561
567 virtual void destroyNode(PQNode<T, X, Y>* nodePtr) {
569 }
570
585 virtual void exchangeNodes(PQNode<T, X, Y>* oldNode, PQNode<T, X, Y>* newNode);
586
595 virtual void linkChildrenOfQnode(PQNode<T, X, Y>* installed, PQNode<T, X, Y>* newChild);
596
607
657
659
661 return nodePtr->partialChildren;
662 }
663
665 return nodePtr->m_leftEndmost;
666 }
667
669 return nodePtr->m_rightEndmost;
670 }
671
673 return nodePtr->getNextSib(other);
674 }
675
677 return nodePtr->m_sibLeft;
678 }
679
681 return nodePtr->m_sibRight;
682 }
683
692
700 virtual const char* clientPrintStatus(PQNode<T, X, Y>* nodePtr);
701
709 virtual const char* clientPrintType(PQNode<T, X, Y>* nodePtr);
710
711private:
733 bool checkChain(PQNode<T, X, Y>* nodePtr, PQNode<T, X, Y>* firstFull,
734 PQNode<T, X, Y>** seqStart, PQNode<T, X, Y>** seqEnd);
735
750
765
782 void removeBlock(PQNode<T, X, Y>* nodePtr, bool isRoot);
783
788 void sortExceptions(int Exceptions[], int arraySize);
789};
790
791template<class T, class X, class Y>
793 SListPure<PQLeafKey<T, X, Y>*>& leafKeys) {
794 if (!leafKeys.empty()) {
795 OGDF_ASSERT(!father->m_childCount);
796 // Father has children. Brothers expected
797
799 SListIterator<PQLeafKey<T, X, Y>*> it = leafKeys.begin();
800 PQLeafKey<T, X, Y>* newKey = *it; //leafKeys[0];
801
802 PQNode<T, X, Y>* aktualSon = new PQLeaf<T, X, Y>(m_identificationNumber++,
804 PQNode<T, X, Y>* firstSon = aktualSon;
805 firstSon->m_parent = father;
806 firstSon->m_parentType = father->type();
807 father->m_childCount++;
808 PQNode<T, X, Y>* oldSon = firstSon;
809
811 for (++it; it.valid(); ++it) {
812 newKey = *it; //leafKeys[i];
813 aktualSon = new PQLeaf<T, X, Y>(m_identificationNumber++,
815 aktualSon->m_parent = father;
816 aktualSon->m_parentType = father->type();
817 father->m_childCount++;
818 oldSon->m_sibRight = aktualSon;
819 aktualSon->m_sibLeft = oldSon;
820 oldSon = aktualSon;
821 }
822 if (father->type() == PQNodeRoot::PQNodeType::PNode)
824 {
825 firstSon->m_sibLeft = oldSon;
826 oldSon->m_sibRight = firstSon;
827 father->m_referenceChild = firstSon;
828 firstSon->m_referenceParent = father;
829 } else if (father->type() == PQNodeRoot::PQNodeType::QNode)
831 {
832 father->m_leftEndmost = firstSon;
833 father->m_rightEndmost = oldSon;
834 }
835 return true;
836 }
837
838 return false;
839}
840
841template<class T, class X, class Y>
845 //parent type not valid.
846
847 if (child != nullptr) {
848 OGDF_ASSERT(parent->m_childCount == 0);
849 //when adding new nodes: Brothers expected.
850 child->m_parent = parent;
851 child->m_parentType = parent->type();
852 parent->m_childCount++;
853
854 /*
855 Set the reference pointers in case that [[parent]] is a $P$-node.
856 If [[parent]] is a $Q$-node, this chunk sets the endmost children
857 of [[parent]]. Since [[child]] is the only child of [[parent]]
858 both endmost pointers are set to [[child]].
859 */
860 if (parent->type() == PQNodeRoot::PQNodeType::PNode) {
861 child->m_sibLeft = child;
862 child->m_sibRight = child;
863 parent->m_referenceChild = child;
864 child->m_referenceParent = parent;
865 } else if (parent->type() == PQNodeRoot::PQNodeType::QNode) {
866 parent->m_leftEndmost = child;
867 parent->m_rightEndmost = child;
868 }
869
870 return true;
871 }
872
873 return false;
874}
875
876template<class T, class X, class Y>
878 PQNode<T, X, Y>* leftBrother, PQNode<T, X, Y>* rightBrother) {
879 if (parent != nullptr) {
881 || parent->type() == PQNodeRoot::PQNodeType::QNode);
882 //parent type not valid
883 if (leftBrother == nullptr && rightBrother == nullptr) {
884 return addNodeToNewParent(parent, child);
885 } else if (child != nullptr) {
886 child->m_parent = parent;
887 child->m_parentType = parent->type();
888 parent->m_childCount++;
889
890 if (parent->type() == PQNodeRoot::PQNodeType::PNode) {
891 /*
892 The parent is a $P$-node with children.
893 Either [[leftBrother]] or [[rightBrother]] stores
894 a pointer to an existing child of [[parent]] and [[parent]]
895 is a $P$-node. In case that two brothers are stored, an
896 arbitrary one is choosen to be the next sibling of [[child]].
897 This brother is stored in [[brother]]. The pointer [[sister]]
898 denotes a pointer to an arbitrary sibling of [[brother]].
899 */
900 PQNode<T, X, Y>* brother = (leftBrother != nullptr) ? leftBrother : rightBrother;
901 PQNode<T, X, Y>* sister = brother->m_sibRight;
902 child->m_sibLeft = brother;
903 child->m_sibRight = sister;
904 brother->m_sibRight = child;
905 sister->m_sibLeft = child;
906 return true;
907 }
908
909 else if (leftBrother == nullptr) {
910 /*
911 The parent is a $Q$-node with children.
912 The [[leftBrother]] is a [[0]]-pointer while the
913 [[rightBrother]] denotes an existing child of [[parent]].
914 The node [[rightBrother]] <b>must be</b> one of the two endmost
915 children of [[parent]]. If this is not the case, the chunk
916 detects this, halts the procedure [[addNewLeavesToTree]]
917 printing an error message and returning [[0]].
918 If [[rightBrother]] is endmost child of [[parent]], then
919 this chunk adds [[child]] at the one end where
920 [[rightBrother]] hides. The node [[child]] is then made the
921 new endmost child of [[parent]] on the corresponding side.
922 */
923 if (rightBrother == parent->m_leftEndmost) {
924 parent->m_leftEndmost = child;
925 child->m_sibRight = rightBrother;
926 rightBrother->putSibling(child, PQNodeRoot::SibDirection::Left);
927 return true;
928 }
929
930 // missing second brother?
931 OGDF_ASSERT(rightBrother == parent->m_rightEndmost);
932 parent->m_rightEndmost = child;
933 child->m_sibLeft = rightBrother;
934 rightBrother->putSibling(child, PQNodeRoot::SibDirection::Left);
935 return true;
936 }
937
938 else if (rightBrother == nullptr) {
939 /*
940 The parent is a $Q$-node with children.
941 The [[rightBrother]] is a [[0]]-pointer while the
942 [[leftBrother]] denotes an existing child of [[parent]]. The
943 node [[leftBrother]] <b>must be</b> one of the two endmost
944 children of [[parent]]. If this is not the case, the chunk
945 detects this, halts the procedure [[addNodeToNewParent]]
946 printing an error message and returning [[0]].
947 If [[leftBrother]] is endmost child of [[parent]], then this
948 chunk adds [[child]] at the one end where [[leftBrother]]
949 hides. The node [[child]] is then made new endmost child of
950 [[parent]] on the corresponding side.
951 */
952 if (leftBrother == parent->m_rightEndmost) {
953 parent->m_rightEndmost = child;
954 child->m_sibLeft = leftBrother;
955 leftBrother->putSibling(child, PQNodeRoot::SibDirection::Right);
956 return true;
957 }
958
959 // missing second brother?
960 OGDF_ASSERT(leftBrother == parent->m_leftEndmost);
961 parent->m_leftEndmost = child;
962 child->m_sibRight = leftBrother;
963 leftBrother->putSibling(child, PQNodeRoot::SibDirection::Right);
964 return true;
965 }
966
967 else {
968 /*
969 The parent is a $Q$-node with children.
970 Both the [[rightBrother]] and the [[leftBrother]] denote
971 existing children of [[parent]]. In this case, [[leftBrother]]
972 and [[rightBrother]] must be immideate siblings. If this is
973 not the case, this will be detected during the function call
974 [[changeSiblings]] of the class [[PQNode.h]] (see
975 \ref{PQNode.changeSiblings}) in the first two lines of this
976 chunk. If the chunk recognizes the failure of
977 [[changeSiblings]] it halts the procedure
978 [[addNewLeavesToTree]], printing an error message and
979 returning [[0]].
980 If the two brothers are immediate siblings, this chunk
981 adds [[child]] between the two brothers as interior child of
982 the $Q$-node [[parent]].
983 */
984#ifdef OGDF_DEBUG
985 bool ok =
986#endif
987 rightBrother->changeSiblings(leftBrother, child)
988 && leftBrother->changeSiblings(rightBrother, child);
989
990 // brothers are not siblings?
991 OGDF_ASSERT(ok);
992
993 if (leftBrother->m_sibRight == child) {
994 child->m_sibLeft = leftBrother;
995 child->m_sibRight = rightBrother;
996 } else {
997 child->m_sibLeft = rightBrother;
998 child->m_sibRight = leftBrother;
999 }
1000 return true;
1001 }
1002 } else {
1003 return false;
1004 }
1005 } else if (leftBrother != nullptr && rightBrother != nullptr) {
1006 /*
1007 The parent is a $Q$-node with children.
1008 Both the [[rightBrother]] and the [[leftBrother]] denote
1009 existing children of [[parent]]. In this case, [[leftBrother]]
1010 and [[rightBrother]] must be immideate siblings. If this is
1011 not the case, this will be detected during the function call
1012 [[changeSiblings]] of the class [[PQNode.h]] (see
1013 \ref{PQNode.changeSiblings}) in the first two lines of this
1014 chunk. If the chunk recognizes the failure of
1015 [[changeSiblings]] it halts the procedure
1016 [[addNewLeavesToTree]], printing an error message and
1017 returning [[0]].
1018 If the two brothers are immediate siblings, this chunk
1019 adds [[child]] between the two brothers as interior child of
1020 the $Q$-node [[parent]].
1021 */
1022#ifdef OGDF_DEBUG
1023 bool ok =
1024#endif
1025 rightBrother->changeSiblings(leftBrother, child)
1026 && leftBrother->changeSiblings(rightBrother, child);
1027
1028 // brothers are not siblings?
1029 OGDF_ASSERT(ok);
1030
1031 if (leftBrother->m_sibRight == child) {
1032 child->m_sibLeft = leftBrother;
1033 child->m_sibRight = rightBrother;
1034 } else {
1035 child->m_sibLeft = rightBrother;
1036 child->m_sibRight = leftBrother;
1037 }
1038 return true;
1039 }
1040
1041 return true;
1042}
1043
1044template<class T, class X, class Y>
1046 /* Variables:
1047 * - \a blockcount is the number of blocks of blocked nodes during
1048 * the bubbling up phase.
1049 * - \a numBlocked is the number of blocked nodes during the
1050 * bubbling up phase.
1051 * - \a blockedSiblings counts the number of blocked siblings that
1052 * are adjacent to \a checkNode. A node has 0, 1 or 2 blocked siblings.
1053 * A child of a P-node has no blocked siblings. Endmost children of
1054 * Q-nodes have at most 1 blocked sibling. The interior children of
1055 * a Q-Node have at most 2 blocked siblings.
1056 * - \a checkLeaf is a pointer used for finding the pertinent leaves.
1057 * - \a checkNode is a pointer to the actual node.
1058 * - \a checkSib is a pointer used to examin the siblings of [[checkNode]].
1059 * - \a offTheTop is a variable which is either 0 (that is its
1060 * initial value) or 1 in case that the root of the tree has been
1061 * process during the first phase.
1062 * - \a parent is a pointer to the parent of \a checkNode, if \a checkNode
1063 * has a valid parent pointer.
1064 * - \a processNodes is a first-in first-out list that is used for
1065 * sequencing the order in which the nodes are processed.
1066 * - \a blockedNodes is a stack storing all nodes that have been
1067 * once blocked. In case that the [[m_pseudoRoot]] has to be
1068 * introduced, the stack contains the blocked nodes.
1069 */
1070 Queue<PQNode<T, X, Y>*> processNodes;
1071
1072 /*
1073 Enter the [[Full]] leaves into the queue [[processNodes]].
1074 In a first step the pertinent leaves have to be identified in the tree
1075 and entered on to the queue [[processNodes]]. The identification of
1076 the leaves can be done with the help of a pointer stored in every
1077 [[PQLeafKey]] (see \ref{PQLeafKey}) in constant time for every element.
1078 */
1080 for (it = leafKeys.begin(); it.valid(); ++it) {
1081 PQNode<T, X, Y>* checkLeaf = (*it)->nodePointer(); //leafKeys[i]->nodePointer();
1083 processNodes.append(checkLeaf);
1084 m_pertinentNodes->pushFront(checkLeaf);
1085 }
1086
1087 int blockCount = 0;
1088 // int numBlocked = 0;
1089 int offTheTop = 0;
1090 PQNode<T, X, Y>* checkSib = nullptr;
1091 ArrayBuffer<PQNode<T, X, Y>*> blockedNodes;
1092
1093 while ((processNodes.size() + blockCount + offTheTop) > 1) {
1094 if (processNodes.size() == 0) {
1095 /*
1096 No consecutive sequence possible.
1097 The queue [[processNodes]] does not contain any nodes for
1098 processing and the sum of [[blockCount]] and [[offTheTop]] is
1099 greater than 1. If the queue is empty, the root of the pertinent
1100 subtree was already processed. Nevertheless, there are blocked
1101 nodes since [[offTheTop]] is either be [[0]] or [[1]], hence
1102 [[blockCount]] must be at least [[1]]. Such blocked nodes cannot
1103 form a consecutive sequence with all nodes in the set
1104 [[leafKeys]]. Observe that this chunk finishes the function
1105 [[Bubble]]. Hence every memory allocated by the function [[Bubble]]
1106 has to be deleted here as well.
1107 */
1108 return false;
1109 }
1110 /*
1111 If there are still nodes to be processed in which case the queue
1112 [[processNodes]] is not empty, we get the next node from the queue.
1113 By default this node has to be marked as blocked.
1114 */
1115 PQNode<T, X, Y>* checkNode = processNodes.pop();
1116 blockedNodes.push(checkNode);
1118 int blockedSiblings = 0;
1119
1120 /*
1121 Check if node is adjacent to an unblocked node.
1122 After getting the node [[checkNode]] from the queue, its siblings are
1123 checked, whether they are unblocked. If they are, then they have a
1124 valid pointer to their parent and the parent pointer of [[checkNode]]
1125 is updated.
1126 */
1127 if (checkNode->m_parentType != PQNodeRoot::PQNodeType::PNode && checkNode != m_root)
1128 // checkNode is son of a QNode.
1129 // Check if it is blocked.
1130 {
1131 if (clientSibLeft(checkNode) == nullptr)
1132 // checkNode is endmost child of
1133 // a QNode. It has a valid pointer
1134 // to its parent.
1135 {
1137 if (clientSibRight(checkNode)
1138 && clientSibRight(checkNode)->mark() == PQNodeRoot::PQNodeMark::Blocked) {
1139 blockedSiblings++;
1140 }
1141 }
1142
1143 else if (clientSibRight(checkNode) == nullptr)
1144 // checkNode is endmost child of
1145 // a QNode. It has a valid pointer
1146 // to its parent.
1147 {
1149 if (clientSibLeft(checkNode)
1150 && clientSibLeft(checkNode)->mark() == PQNodeRoot::PQNodeMark::Blocked) {
1151 blockedSiblings++;
1152 }
1153 }
1154
1155
1156 else
1157 // checkNode is not endmost child of
1158 // a QNode. It has not a valid
1159 // pointer to its parent.
1160 {
1161 if (clientSibLeft(checkNode)->mark() == PQNodeRoot::PQNodeMark::Unblocked)
1162 // checkNode is adjacent to an
1163 // unblocked node. Take its parent.
1164 {
1166 checkNode->m_parent = clientSibLeft(checkNode)->m_parent;
1167 } else if (clientSibLeft(checkNode)->mark() == PQNodeRoot::PQNodeMark::Blocked) {
1168 blockedSiblings++;
1169 }
1170
1171 if (clientSibRight(checkNode)->mark() == PQNodeRoot::PQNodeMark::Unblocked)
1172 // checkNode is adjacent to an
1173 // unblocked node. Take its parent.
1174 {
1176 checkNode->m_parent = clientSibRight(checkNode)->m_parent;
1177 } else if (clientSibRight(checkNode)->mark() == PQNodeRoot::PQNodeMark::Blocked) {
1178 blockedSiblings++;
1179 }
1180 }
1181 }
1182
1183 else {
1184 // checkNode is son of a PNode
1185 // and children of P_NODEs
1186 // cannot be blocked.
1188 }
1189
1190 if (checkNode->mark() == PQNodeRoot::PQNodeMark::Unblocked) {
1191 PQNode<T, X, Y>* parent = checkNode->m_parent;
1192
1193 /*
1194 Get maximal consecutive set of blocked siblings.
1195 This chunk belongs to the procedure [[bubble]].
1196 The node [[checkNode]] is [[Unblocked]].
1197 If the parent of [[checkNode]] is a $Q$-Node, then we check the
1198 siblings [[checkSib]] of [[checkNode]] whether they are
1199 [[Blocked]]. If they are blocked, they have to be marked
1200 [[Unblocked]] since they are adjacent to the [[Unblocked]] node
1201 [[checkNode]]. We then have to proceed with the siblings of
1202 [[checkSib]] in order to find [[Blocked]] nodes
1203 adjacent to [[checkSib]]. This is repeated until no [[Blocked]]
1204 nodes are found any more.
1205
1206 Observe that while running through the children of the $Q$-Node
1207 (referred by the pointer [[parent]]), their parent pointers,
1208 as well as the [[pertChildCount]] of [[parent]] are updated.
1209 Furthermore we reduce simultaneously the count [[numBlocked]].
1210 */
1211 if (blockedSiblings > 0) {
1212 if (clientSibLeft(checkNode) != nullptr) {
1213 checkSib = clientSibLeft(checkNode);
1214 PQNode<T, X, Y>* oldSib = checkNode;
1215 while (checkSib->mark() == PQNodeRoot::PQNodeMark::Blocked) {
1217 checkSib->m_parent = parent;
1218 // numBlocked--;
1219 parent->m_pertChildCount++;
1220 PQNode<T, X, Y>* holdSib = clientNextSib(checkSib, oldSib);
1221 oldSib = checkSib;
1222 checkSib = holdSib;
1223 // Blocked node as endmost child of a QNode.
1224 }
1225 }
1226
1227 if (clientSibRight(checkNode) != nullptr) {
1228 checkSib = clientSibRight(checkNode);
1229 PQNode<T, X, Y>* oldSib = checkNode;
1230 while (checkSib->mark() == PQNodeRoot::PQNodeMark::Blocked) {
1232 checkSib->m_parent = parent;
1233 // numBlocked--;
1234 parent->m_pertChildCount++;
1235 PQNode<T, X, Y>* holdSib = clientNextSib(checkSib, oldSib);
1236 oldSib = checkSib;
1237 checkSib = holdSib;
1238 // Blocked node as endmost child of a QNode.
1239 }
1240 }
1241 }
1242
1243 /*
1244 Process parent of [[checkNode]]
1245 After processing the siblings of the [[Unblocked]] [[checkNode]]
1246 the parent has to be processed. If [[checkNode]] is the root
1247 of the tree we do nothing except setting the flag [[offTheTop]].
1248 If it is not the root and [[parent]] has not been placed onto the
1249 queue [[processNodes]], the [[parent]] is placed on to
1250 [[processNodes]].
1251
1252 Observe that the number [[blockCount]] is updated. Since
1253 [[checkNode]] was [[Unblocked]] all pertinent nodes adjacent
1254 to that node became [[Unblocked]] as well. Therefore the number
1255 of blocks is reduced by the number of [[Blocked]] siblings of
1256 [[checkNode]].
1257 */
1258 if (parent == nullptr) {
1259 // checkNode is root of the tree.
1260 offTheTop = 1;
1261 } else
1262 // checkNode is not the root.
1263 {
1264 parent->m_pertChildCount++;
1265 if (parent->mark() == PQNodeRoot::PQNodeMark::Unmarked) {
1266 processNodes.append(parent);
1267 m_pertinentNodes->pushFront(parent);
1269 }
1270 }
1271
1272 blockCount -= blockedSiblings;
1273 blockedSiblings = 0;
1274 } else {
1275 /*
1276 Process blocked [[checkNode]]
1277 Since [[checkNode]] is [[Blocked]], we cannot continue
1278 processing at this point in the Tree. We have to wait until
1279 this node becomes unblocked. So only the variables
1280 [[blockCount]] and [[numBlocked]] are updated.
1281 */
1282 blockCount += 1 - blockedSiblings;
1283 // numBlocked++;
1284 }
1285 }
1286
1287 if (blockCount == 1) {
1288 /*
1289 If [[blockCount]] $= 1$ enter [[m_pseudoRoot]] to the tree
1290 In case that the root of the pertinent subtree is a $Q$-node
1291 with empty children on both sides and the pertinent children
1292 in the middle, it is possible that the $PQ$-tree is reducible.
1293 But since the sequence of pertinent children of the $Q$-node is
1294 blocked, the procedure is not able to find the parent of its
1295 pertinent children. This is due to the fact that the interior
1296 children of a $Q$-node do not have a valid parent pointer.
1297
1298 So the root of the pertinent subtree is not known, hence cannot be
1299 entered into the processing queue used in the function call [[Reduce]]
1300 (see \ref{Reduce}). To solve this problem a special node only designed
1301 for this cases is used: [[m_pseudoRoot]]. It simulates the root of the
1302 pertinent subtree. This works out well, since for this node the only
1303 possible template maching is [[templateQ3]] (see \ref{templateQ3}),
1304 where no pointers to the endmost children of a $Q$-node are used.
1305 */
1306 while (!blockedNodes.empty()) {
1307 PQNode<T, X, Y>* checkNode = blockedNodes.popRet();
1308 if (checkNode->mark() == PQNodeRoot::PQNodeMark::Blocked) {
1310 checkNode->m_parent = m_pseudoRoot;
1311 m_pseudoRoot->m_pertChildCount++;
1312 OGDF_ASSERT(!checkNode->endmostChild());
1313 //Blocked node as endmost child of a QNode.
1314 }
1315 }
1316 }
1317
1318 return true;
1319}
1320
1321template<class T, class X, class Y>
1323 PQNode<T, X, Y>** seqStart, PQNode<T, X, Y>** seqEnd) {
1324 /* Variables:
1325 * - \a fullCount counts the number of children that are
1326 * discovered by the function checkChain(). This is necessary, since
1327 * checkChain() is used by two template matching functions
1328 * templateQ2() and templateQ3() where in the latter case the
1329 * pointer \a firstFull may point to any full child in the front of the Q-node
1330 * \a nodePtr.
1331 * - \a notFull is set 1 when an empty child is encountered.
1332 * - \a checkNode is the actual node that is examined.
1333 * - \a leftNext is the next node that has to be examined on the
1334 * left side of \a firstFull.
1335 * - \a leftOld is the node that has been examined right before
1336 * \a checkNode on the left side of \a firstFull.
1337 * - \a rightNext is the next node that has to be examined on the
1338 * right side of \a firstFull. Not needed when checkChain() was
1339 * called by templateQ2().
1340 * - \a rightOld is the node that has been examined right before
1341 * \a checkNode on the right side of \a firstFull.
1342 * Not needed when checkChain() was called by templateQ2().
1343 */
1344 bool notFull = false;
1345 int fullCount = nodePtr->fullChildren->size();
1346 fullCount--; // firstFull does have a Full label.
1347
1348 /*
1349 Start at the [[firstFull]] child sweeping through the full children on
1350 the left side of [[firstfull]]. It stops as soon as a nonfull child is
1351 detected. The last found full child is stored in [[seqEnd]].
1352 */
1353 PQNode<T, X, Y>* leftNext = clientSibLeft(firstFull);
1354 (*seqEnd) = firstFull;
1355 if (leftNext != nullptr) {
1356 if (leftNext->status() == PQNodeRoot::PQNodeStatus::Full) {
1357 fullCount--;
1358
1359 PQNode<T, X, Y>* leftOld = firstFull;
1360 PQNode<T, X, Y>* checkNode = leftNext;
1361
1362 while (fullCount > 0 && !notFull)
1363 // There are still full children to be
1364 // counted, and no empty child has been
1365 // encountered on this side.
1366 {
1367 leftNext = clientNextSib(checkNode, leftOld);
1368 if (leftNext != nullptr && leftNext->status() == PQNodeRoot::PQNodeStatus::Full) {
1369 fullCount--;
1370 } else {
1371 notFull = true;
1372 }
1373 leftOld = checkNode;
1374 checkNode = leftNext;
1375 }
1376
1377 if (checkNode != nullptr && checkNode->status() == PQNodeRoot::PQNodeStatus::Full) {
1378 (*seqEnd) = checkNode;
1379 }
1380
1381 else {
1382 //searching consecutive sequence in Q2 or Q3.
1383 OGDF_ASSERT(leftOld != nullptr);
1385 (*seqEnd) = leftOld;
1386 }
1387
1388 } else {
1389 (*seqEnd) = firstFull;
1390 }
1391 }
1392
1393 /*
1394 Start at the [[firstFull]] child sweeping through the full children on
1395 the right side of [[firstfull]]. It stops as soon as a nonfull child is
1396 detected.
1397 */
1398 notFull = false;
1399 PQNode<T, X, Y>* rightNext = clientSibRight(firstFull);
1400 (*seqStart) = firstFull;
1401 if (rightNext != nullptr) {
1402 if (rightNext->status() == PQNodeRoot::PQNodeStatus::Full) {
1403 fullCount--;
1404
1405 PQNode<T, X, Y>* rightOld = firstFull;
1406 PQNode<T, X, Y>* checkNode = rightNext;
1407
1408 while (fullCount > 0 && !notFull)
1409 // There are still full children to be
1410 // counted, and no empty child has been
1411 // encountered on this side.
1412 {
1413 rightNext = clientNextSib(checkNode, rightOld);
1414 if (rightNext != nullptr && rightNext->status() == PQNodeRoot::PQNodeStatus::Full) {
1415 fullCount--;
1416 } else {
1417 notFull = true;
1418 }
1419 rightOld = checkNode;
1420 checkNode = rightNext;
1421 }
1422 if (checkNode != nullptr && checkNode->status() == PQNodeRoot::PQNodeStatus::Full) {
1423 (*seqStart) = checkNode;
1424 }
1425
1426 else {
1427 OGDF_ASSERT(rightOld != nullptr);
1429 (*seqStart) = rightOld;
1430 //searching consecutive seqeuence in Q2 or Q3.
1431 }
1432
1433 } else {
1434 (*seqStart) = firstFull;
1435 }
1436 }
1437
1438 if (firstFull == (*seqEnd)) {
1439 PQNode<T, X, Y>* checkNode = (*seqEnd);
1440 (*seqEnd) = (*seqStart);
1441 (*seqStart) = checkNode;
1442 }
1443
1444 if (fullCount == 0) {
1445 // All full children occupy a consecutive
1446 // sequence.
1447 return true;
1448 } else {
1449 return false;
1450 }
1451}
1452
1453template<class T, class X, class Y>
1455 if ((parent->type() == PQNodeRoot::PQNodeType::PNode && parent->m_childCount == 1)
1456 || (parent->type() == PQNodeRoot::PQNodeType::QNode && parent->m_leftEndmost == child
1457 && parent->m_rightEndmost == child)) {
1458 removeChildFromSiblings(child);
1459 child->m_parent = parent->m_parent;
1460 if (parent->m_parent != nullptr) { // parent is not the root.
1461 exchangeNodes(parent, child);
1462 } else {
1463 exchangeNodes(parent, child);
1464 m_root = child;
1465 }
1466 destroyNode(parent);
1467 return true;
1468 } else {
1469 return false;
1470 }
1471}
1472
1473template<class T, class X, class Y>
1475 /* In order to free the allocated memory, all nodes of the
1476 * tree have to be deleted, hence there destructors are called.
1477 * In order to achieve this, we start at the root of the tree and go down the
1478 * tree to the leaves for reaching every node. When a node is processed,
1479 * (besides the #m_root, this will always be the node \a checkNode)
1480 * the pointers of all its children are stored in a queue \a helpqueue and
1481 * then the processed node is deleted.
1482 *
1483 * The use of a queue \a helpqueue is a must, since the nodes do not
1484 * have pointers to all of their children, as the children mostly do
1485 * not have a pointer to their parent.
1486 *
1487 * It might look weird at the first glance that the function Cleanup()
1488 * calls the function emptyAllPertinentNodes(), but if some nodes were removed
1489 * during a reduction, they were stored in the stack #m_pertinentNodes.
1490 * These nodes have to be deleted as well
1491 * which is provided by the function emptyAllPertinentNodes().
1492 */
1493 PQNode<T, X, Y>* nextSon = nullptr;
1494 PQNode<T, X, Y>* lastSon = nullptr;
1495
1496 Queue<PQNode<T, X, Y>*> helpqueue;
1497
1498 if (m_root != nullptr) {
1499 emptyAllPertinentNodes();
1500 OGDF_ASSERT(m_root != nullptr);
1501 PQNode<T, X, Y>* oldSib = nullptr;
1502
1503 /*
1504 Process the [[m_root]] of the [[PQTree]]. Before deleting [[m_root]],
1505 pointers to all its children are stored in the queue [[helpqueue]].
1506 */
1507 if (m_root->type() == PQNodeRoot::PQNodeType::PNode) {
1508 if (m_root->m_referenceChild != nullptr) {
1509 PQNode<T, X, Y>* firstSon = m_root->m_referenceChild;
1510 helpqueue.append(firstSon);
1511
1512 if (firstSon->m_sibRight != nullptr) {
1513 nextSon = firstSon->m_sibRight;
1514 }
1515 while (nextSon != firstSon) {
1516 helpqueue.append(nextSon);
1517 nextSon = nextSon->m_sibRight;
1518 }
1519 }
1520 } else if (m_root->type() == PQNodeRoot::PQNodeType::QNode) {
1521 PQNode<T, X, Y>* firstSon = m_root->m_leftEndmost;
1522 helpqueue.append(firstSon);
1523
1524 lastSon = m_root->m_rightEndmost;
1525 helpqueue.append(lastSon);
1526
1527 nextSon = lastSon->getNextSib(oldSib);
1528 oldSib = lastSon;
1529 while (nextSon != firstSon) {
1530 helpqueue.append(nextSon);
1531 PQNode<T, X, Y>* holdSib = nextSon->getNextSib(oldSib);
1532 oldSib = nextSon;
1533 nextSon = holdSib;
1534 }
1535 }
1536
1537
1538 CleanNode(m_root);
1539 delete m_root;
1540
1541 while (!helpqueue.empty()) {
1542 PQNode<T, X, Y>* checkNode = helpqueue.pop();
1543
1544 /*
1545 Process an arbitrary node [[checkNode]] of the [[PQTree]].
1546 Before deleting [[checkNode]],
1547 pointers to all its children are stored in the queue [[helpqueue]].
1548 */
1549 if (checkNode->type() == PQNodeRoot::PQNodeType::PNode) {
1550 if (checkNode->m_referenceChild != nullptr) {
1551 PQNode<T, X, Y>* firstSon = checkNode->m_referenceChild;
1552 helpqueue.append(firstSon);
1553
1554 if (firstSon->m_sibRight != nullptr) {
1555 nextSon = firstSon->m_sibRight;
1556 }
1557 while (nextSon != firstSon) {
1558 helpqueue.append(nextSon);
1559 nextSon = nextSon->m_sibRight;
1560 }
1561 }
1562 } else if (checkNode->type() == PQNodeRoot::PQNodeType::QNode) {
1563 oldSib = nullptr;
1564
1565 PQNode<T, X, Y>* firstSon = checkNode->m_leftEndmost;
1566 helpqueue.append(firstSon);
1567
1568 lastSon = checkNode->m_rightEndmost;
1569 helpqueue.append(lastSon);
1570
1571 nextSon = lastSon->getNextSib(oldSib);
1572 oldSib = lastSon;
1573 while (nextSon != firstSon) {
1574 helpqueue.append(nextSon);
1575 PQNode<T, X, Y>* holdSib = nextSon->getNextSib(oldSib);
1576 oldSib = nextSon;
1577 nextSon = holdSib;
1578 }
1579 }
1580
1581 CleanNode(checkNode);
1582 delete checkNode;
1583 }
1584 }
1585
1586 CleanNode(m_pseudoRoot);
1587 delete m_pseudoRoot;
1588
1589 delete m_pertinentNodes;
1590
1591 m_root = nullptr;
1592 m_pertinentRoot = nullptr;
1593 m_pseudoRoot = nullptr;
1594 m_pertinentNodes = nullptr;
1595
1596 m_numberOfLeaves = 0;
1597 m_identificationNumber = 0;
1598}
1599
1600template<class T, class X, class Y>
1602 return (nodePtr != nullptr) ? 1 : 0;
1603 // 1 is the standard node categrie in the Tree Interface.
1604}
1605
1606template<class T, class X, class Y>
1608 return (nodePtr != nullptr) ? "ERROR" : "ERROR: clientPrintStatus: NO NODE ACCESSED";
1609}
1610
1611template<class T, class X, class Y>
1613 return (nodePtr != nullptr) ? "ERROR" : "ERROR: clientPrintType: NO NODE ACCESSED";
1614}
1615
1616template<class T, class X, class Y>
1618 m_root = nullptr;
1619 m_pertinentRoot = nullptr;
1620 m_pseudoRoot = nullptr;
1621
1622 m_numberOfLeaves = 0;
1623 m_identificationNumber = 0;
1624
1625 m_pertinentNodes = nullptr;
1626}
1627
1628template<class T, class X, class Y>
1630 PQNode<T, X, Y>* partialChild) {
1631 if (nodePtr->fullChildren->size() > 0)
1632 // There are some full children to
1633 // be copied.
1634 {
1635 nodePtr->m_childCount = nodePtr->m_childCount - nodePtr->fullChildren->size();
1636
1637 PQNode<T, X, Y>* newNode = createNodeAndCopyFullChildren(nodePtr->fullChildren);
1638
1639 // Introduce newNode as endmost
1640 // child of the partial Q-node.
1641 partialChild->m_childCount++;
1642 partialChild->fullChildren->pushFront(newNode);
1643
1644 if (clientLeftEndmost(partialChild)->status() == PQNodeRoot::PQNodeStatus::Full) {
1645 PQNode<T, X, Y>* checkNode = partialChild->m_leftEndmost;
1646 partialChild->m_leftEndmost = newNode;
1647 linkChildrenOfQnode(checkNode, newNode);
1648
1649 } else {
1650 // ERROR: Endmostchild not found?
1651 OGDF_ASSERT(clientRightEndmost(partialChild)->status() == PQNodeRoot::PQNodeStatus::Full);
1652
1653 PQNode<T, X, Y>* checkNode = partialChild->m_rightEndmost;
1654 partialChild->m_rightEndmost = newNode;
1655 linkChildrenOfQnode(checkNode, newNode);
1656 }
1657
1658 newNode->m_parent = partialChild;
1660 }
1661}
1662
1663template<class T, class X, class Y>
1665 /* Variables:
1666 * - \a newNode stores the adress of the new allocated P-node or
1667 * the adress of the only full child.
1668 * - \a oldSon is a variable used for adding the full nodes as
1669 * children to the new P-node.
1670 * - \a firstSon stores the adress of the first detected full
1671 * child. It is needed for adding the full nodes as
1672 * children to the new P-node.
1673 * - \a checkSon is a variable used for adding the full nodes as
1674 * children to the new P-node.
1675 * - \a newPQnode is used for proper allocation of the new P-node.
1676 */
1677 PQNode<T, X, Y>* newNode = nullptr;
1678
1679 if (fullNodes->size() == 1) {
1680 /*
1681 There is just one full child. So no new $P$-node is created. The
1682 full child is copied as child to the [[partialChild]].
1683 */
1684 newNode = fullNodes->popFrontRet();
1685 removeChildFromSiblings(newNode);
1686 }
1687
1688 else {
1689 /*
1690 This chunk belongs to the function [[createNodeAndCopyFullChildren]].
1691 There is more than one full child, so a new $P$-node is created.
1692 This chunk first allocates the memory for the new $P$-node that will
1693 be stored in [[newNode]]. Then it pops the nodes out of the stack
1694 [[fullNodes]] and introduces them as sons of [[newNode]].
1695 Popping the nodes out of the stack implies at the same time
1696 that they are removed from the [[fullChildren]] stack of the
1697 $P$-node of their parent.
1698 */
1699 newNode = new PQInternalNode<T, X, Y>(m_identificationNumber++,
1701 m_pertinentNodes->pushFront(newNode);
1702 newNode->m_pertChildCount = fullNodes->size();
1703 newNode->m_childCount = fullNodes->size();
1704
1705 /*
1706 The first node is copied separately, since we need the pointer to it
1707 for setting the pointers to the siblings of the next full nodes.
1708 */
1709 PQNode<T, X, Y>* firstSon = fullNodes->popFrontRet();
1710 removeChildFromSiblings(firstSon);
1711 newNode->fullChildren->pushFront(firstSon);
1712 firstSon->m_parent = newNode;
1713 firstSon->m_parentType = newNode->type();
1714 PQNode<T, X, Y>* oldSon = firstSon;
1715
1716
1717 /*
1718 All remaining nodes that are stored in the stack [[fullNodes]] are
1719 introduced as children of the new $P$-node [[newNode]]. Observe
1720 that the children of a $P$-node must form a doubly linked list.
1721 Hence the last node and the [[firstSon]] must be linked via their
1722 siblings pointers.
1723 */
1724 while (!fullNodes->empty()) {
1725 PQNode<T, X, Y>* checkSon = fullNodes->popFrontRet();
1726 removeChildFromSiblings(checkSon);
1727 newNode->fullChildren->pushFront(checkSon);
1728 oldSon->m_sibRight = checkSon;
1729 checkSon->m_sibLeft = oldSon;
1730 checkSon->m_parent = newNode;
1731 checkSon->m_parentType = newNode->type();
1732 oldSon = checkSon;
1733 }
1734 firstSon->m_sibLeft = oldSon;
1735 oldSon->m_sibRight = firstSon;
1736 newNode->m_referenceChild = firstSon;
1737 firstSon->m_referenceParent = newNode;
1738 }
1739
1740 return newNode;
1741}
1742
1743template<class T, class X, class Y>
1745 while (!m_pertinentNodes->empty()) {
1746 PQNode<T, X, Y>* nodePtr = m_pertinentNodes->popFrontRet();
1747 switch (nodePtr->status()) {
1749 if (nodePtr == m_root) {
1750 m_root = nullptr;
1751 }
1752 CleanNode(nodePtr);
1753 OGDF_ASSERT(nodePtr);
1754 delete nodePtr;
1755 break;
1756
1758 emptyNode(nodePtr);
1759 break;
1760
1762 emptyNode(nodePtr);
1763 break;
1764
1765 default:
1766 clientDefinedEmptyNode(nodePtr);
1767 break;
1768 }
1769 }
1770 m_pseudoRoot->m_pertChildCount = 0;
1771 m_pseudoRoot->m_pertLeafCount = 0;
1772 m_pseudoRoot->fullChildren->clear();
1773 m_pseudoRoot->partialChildren->clear();
1774 m_pseudoRoot->status(PQNodeRoot::PQNodeStatus::Empty);
1775 m_pseudoRoot->mark(PQNodeRoot::PQNodeMark::Unmarked);
1776}
1777
1778template<class T, class X, class Y>
1781 nodePtr->m_pertChildCount = 0;
1782 nodePtr->m_pertLeafCount = 0;
1783 nodePtr->fullChildren->clear();
1784 nodePtr->partialChildren->clear();
1786}
1787
1788template<class T, class X, class Y>
1790 if (oldNode->m_referenceParent != nullptr) {
1791 /*
1792 The node [[oldNode]] is connected to its parent
1793 via the reference pointer of the doubly linked list. The [[newNode]]
1794 will be the new reference child and is linked via the reference
1795 pointers to the $P$-node.
1796 */
1797 oldNode->m_referenceParent->m_referenceChild = newNode;
1798 newNode->m_referenceParent = oldNode->m_referenceParent;
1799 oldNode->m_referenceParent = nullptr;
1800 }
1801
1802 else if (oldNode->endmostChild()) {
1803 /*
1804 The [[oldNode]] is endmost child of a Q-node. So its parent
1805 contains an extra pointer to [[oldNode]]. Link the parent of
1806 [[oldNode]] to [[newNode]] via this pointer and make [[newNode]]
1807 endmost child of its new parent.
1808 */
1809 if (oldNode->m_parent->m_leftEndmost == oldNode) {
1810 oldNode->m_parent->m_leftEndmost = newNode;
1811 } else if (oldNode->m_parent->m_rightEndmost == oldNode) {
1812 oldNode->m_parent->m_rightEndmost = newNode;
1813 }
1814 }
1815
1816 if (oldNode->m_sibLeft == oldNode && oldNode->m_sibRight == oldNode) {
1817 /*
1818 Two possible cases are occured.
1819 \begin{enumerate}
1820 \item [[oldNode]] is the only child of a $P$-node. In order to
1821 implement the doubly linked list of children of the $P$-node, the sibling
1822 pointers of [[newNode]] are set to [[newNode]].
1823 \item [[oldNode]] is the [[m_root]] of the $PQ$-tree. Since
1824 by our definition of the $PQ$-tree the sibling pointers of the
1825 [[m_root]] point to the root itself, (i.e. to make sure that
1826 checking for the endmost child property is also valid for the root)
1827 the sibling pointers of [[newNode]] are set to [[newNode]] as well.
1828 \end{enumerate}
1829 */
1830 oldNode->m_sibLeft = nullptr;
1831 oldNode->m_sibRight = nullptr;
1832 if (oldNode->m_parent == nullptr) {
1833 newNode->m_sibLeft = newNode;
1834 newNode->m_sibRight = newNode;
1835 } else {
1836 newNode->m_sibLeft = newNode;
1837 newNode->m_sibRight = newNode;
1838 }
1839 } else {
1840 OGDF_ASSERT(!(oldNode->m_sibLeft == oldNode));
1841 //sibling pointers of old node are not compatible
1842 OGDF_ASSERT(!(oldNode->m_sibRight == oldNode));
1843 //sibling pointers of old node are not compatible.
1844 }
1845 /*
1846 Manage the exchange of [[oldNode]] and [[newNode]] according to
1847 [[oldNode]]'s siblings. The chunk checks both siblings of
1848 [[oldNode]] and resets the sibling pointers of [[oldNode]]'s siblings
1849 as well as the sibling pointers of [[newNode]].
1850 */
1851 if (oldNode->m_sibLeft != nullptr) {
1852 if (oldNode->m_sibLeft->m_sibRight == oldNode) {
1853 oldNode->m_sibLeft->m_sibRight = newNode;
1854 } else {
1855 // Sibling was not connected to child?
1856 OGDF_ASSERT(oldNode->m_sibLeft->m_sibLeft == oldNode);
1857 oldNode->m_sibLeft->m_sibLeft = newNode;
1858 }
1859 newNode->m_sibLeft = oldNode->m_sibLeft;
1860 oldNode->m_sibLeft = nullptr;
1861 }
1862
1863 if (oldNode->m_sibRight != nullptr) {
1864 if (oldNode->m_sibRight->m_sibLeft == oldNode) {
1865 oldNode->m_sibRight->m_sibLeft = newNode;
1866 } else {
1867 // Sibling was not connected to child?
1868 OGDF_ASSERT(oldNode->m_sibRight->m_sibRight == oldNode);
1869 oldNode->m_sibRight->m_sibRight = newNode;
1870 }
1871 newNode->m_sibRight = oldNode->m_sibRight;
1872 oldNode->m_sibRight = nullptr;
1873 }
1874
1875 newNode->m_parentType = oldNode->m_parentType;
1876 newNode->m_parent = oldNode->m_parent;
1877}
1878
1879template<class T, class X, class Y>
1881 Queue<PQNode<T, X, Y>*> helpqueue;
1882 helpqueue.append(nodePtr);
1883
1884 while (!helpqueue.empty()) {
1885 PQNode<T, X, Y>* checkNode = helpqueue.pop();
1886
1887 if (checkNode->type() == PQNodeRoot::PQNodeType::Leaf) {
1888 leafKeys.pushBack(checkNode->getKey());
1889 } else {
1890 PQNode<T, X, Y>* firstSon = nullptr;
1891 PQNode<T, X, Y>* nextSon = nullptr;
1892 PQNode<T, X, Y>* oldSib = nullptr;
1893 PQNode<T, X, Y>* holdSib = nullptr;
1894
1895 if (checkNode->type() == PQNodeRoot::PQNodeType::PNode) {
1896 OGDF_ASSERT(checkNode->m_referenceChild);
1897 firstSon = checkNode->m_referenceChild;
1898 } else if (checkNode->type() == PQNodeRoot::PQNodeType::QNode) {
1899 OGDF_ASSERT(checkNode->m_leftEndmost);
1900 firstSon = checkNode->m_leftEndmost;
1901 }
1902 helpqueue.append(firstSon);
1903 nextSon = firstSon->getNextSib(oldSib);
1904 oldSib = firstSon;
1905 while (nextSon && nextSon != firstSon) {
1906 helpqueue.append(nextSon);
1907 holdSib = nextSon->getNextSib(oldSib);
1908 oldSib = nextSon;
1909 nextSon = holdSib;
1910 }
1911 }
1912 }
1913}
1914
1915template<class T, class X, class Y>
1917 m_pertinentNodes = new List<PQNode<T, X, Y>*>;
1918
1919 if (!leafKeys.empty()) {
1922 m_pseudoRoot = newNode2;
1923
1924 if (leafKeys.begin() != leafKeys.end()) // at least two elements
1925 {
1926 PQInternalNode<T, X, Y>* newNode = new PQInternalNode<T, X, Y>(m_identificationNumber++,
1928 m_root = newNode;
1929 m_root->m_sibLeft = m_root;
1930 m_root->m_sibRight = m_root;
1931 return addNewLeavesToTree(newNode, leafKeys);
1932 }
1933 PQLeaf<T, X, Y>* newLeaf = new PQLeaf<T, X, Y>(m_identificationNumber++,
1934 PQNodeRoot::PQNodeStatus::Empty, *leafKeys.begin());
1935 m_root = newLeaf;
1936 m_root->m_sibLeft = m_root;
1937 m_root->m_sibRight = m_root;
1938 return 1;
1939 }
1940
1941 return 0;
1942}
1943
1944template<class T, class X, class Y>
1946 if (installed != nullptr && newChild != nullptr) {
1947 if (installed->m_sibLeft == nullptr) {
1948 installed->m_sibLeft = newChild;
1949 if (newChild->m_sibRight == nullptr) {
1950 newChild->m_sibRight = installed;
1951 } else {
1952 newChild->m_sibLeft = installed;
1953 }
1954 } else {
1955 // endmost child with 2 siblings encountered?
1956 OGDF_ASSERT(installed->m_sibRight == nullptr);
1957
1958 installed->m_sibRight = newChild;
1959 if (newChild->m_sibLeft == nullptr) {
1960 newChild->m_sibLeft = installed;
1961 } else {
1962 newChild->m_sibRight = installed;
1963 }
1964 }
1965 }
1966}
1967
1968template<class T, class X, class Y>
1969void PQTree<T, X, Y>::writeGML(const char* fileName) {
1970 std::ofstream os(fileName);
1971 writeGML(os);
1972}
1973
1974template<class T, class X, class Y>
1975void PQTree<T, X, Y>::writeGML(std::ostream& os) {
1976 Array<int> id(0, m_identificationNumber, 0);
1977 int nextId = 0;
1978
1979 SListPure<PQNode<T, X, Y>*> helpQueue;
1980 SListPure<PQNode<T, X, Y>*> secondTrace;
1981
1982 os.setf(std::ios::showpoint);
1983 os.precision(10);
1984
1985 os << "Creator \"ogdf::PQTree::writeGML\"\n";
1986 os << "graph [\n";
1987 os << " directed 1\n";
1988
1989 PQNode<T, X, Y>* checkNode = m_root;
1990 PQNode<T, X, Y>* firstSon = 0;
1991 PQNode<T, X, Y>* nextSon = 0;
1992 PQNode<T, X, Y>* lastSon = 0;
1993 PQNode<T, X, Y>* oldSib = 0;
1994 PQNode<T, X, Y>* holdSib = 0;
1995
1996 if (checkNode->type() != PQNodeRoot::PQNodeType::Leaf) {
1997 secondTrace.pushBack(checkNode);
1998 }
1999
2000 while (checkNode) {
2001 os << " node [\n";
2002
2003 os << " id " << (id[checkNode->m_identificationNumber] = nextId++) << "\n";
2004
2005 os << " label \"" << checkNode->m_identificationNumber;
2006 if (checkNode->getKey() != 0) {
2007 checkNode->getKey()->print(os);
2008 }
2009 os << "\"\n";
2010
2011 os << " graphics [\n";
2012 if (m_root->status() == PQNodeRoot::PQNodeStatus::Full) {
2013 if (checkNode->type() == PQNodeRoot::PQNodeType::PNode) {
2014 os << " fill \"#FF0000\"\n";
2015 } else if (checkNode->type() == PQNodeRoot::PQNodeType::QNode) {
2016 os << " fill \"#0000A0\"\n";
2017 } else if (checkNode->type() == PQNodeRoot::PQNodeType::Leaf) {
2018 os << "fill \"#FFFFE6\"\n";
2019 }
2020 } else if (m_root->status() == PQNodeRoot::PQNodeStatus::Empty) {
2021 if (checkNode->type() == PQNodeRoot::PQNodeType::PNode) {
2022 os << " fill \"#FF0000\"\n";
2023 } else if (checkNode->type() == PQNodeRoot::PQNodeType::QNode) {
2024 os << " fill \"#0000A0\"\n";
2025 } else if (checkNode->type() == PQNodeRoot::PQNodeType::Leaf) {
2026 os << " fill \"#00FF00\"\n";
2027 }
2028 } else if (m_root->status() == PQNodeRoot::PQNodeStatus::Partial) {
2029 if (checkNode->type() == PQNodeRoot::PQNodeType::PNode) {
2030 os << " fill \"#FF0000\"\n";
2031 } else if (checkNode->type() == PQNodeRoot::PQNodeType::QNode) {
2032 os << " fill \"#0000A0\"\n";
2033 } else if (checkNode->type() == PQNodeRoot::PQNodeType::Leaf) {
2034 os << " fill \"#FFFFE6\"\n";
2035 }
2036 } else if (m_root->status() == PQNodeRoot::PQNodeStatus::Pertinent) {
2037 if (checkNode->type() == PQNodeRoot::PQNodeType::PNode) {
2038 os << " fill \"#FF0000\"\n";
2039 } else if (checkNode->type() == PQNodeRoot::PQNodeType::QNode) {
2040 os << " fill \"#0000A0\"\n";
2041 } else if (checkNode->type() == PQNodeRoot::PQNodeType::Leaf) {
2042 os << " fill \"#FFFFE6\"\n";
2043 }
2044 }
2045
2046 os << " ]\n"; // graphics
2047 os << " ]\n"; // node
2048
2049 if (checkNode->type() == PQNodeRoot::PQNodeType::PNode) {
2050 if (checkNode->m_referenceChild != 0) {
2051 firstSon = checkNode->m_referenceChild;
2052 helpQueue.pushBack(firstSon);
2053
2054 if (firstSon->m_sibRight != 0) {
2055 nextSon = firstSon->m_sibRight;
2056 }
2057 while (nextSon != firstSon) {
2058 helpQueue.pushBack(nextSon);
2059 nextSon = nextSon->m_sibRight;
2060 }
2061 }
2062 } else if (checkNode->type() == PQNodeRoot::PQNodeType::QNode) {
2063 oldSib = 0;
2064 holdSib = 0;
2065
2066 firstSon = checkNode->m_leftEndmost;
2067 helpQueue.pushBack(firstSon);
2068
2069 lastSon = checkNode->m_rightEndmost;
2070 if (firstSon != lastSon) {
2071 helpQueue.pushBack(lastSon);
2072 nextSon = lastSon->getNextSib(oldSib);
2073 oldSib = lastSon;
2074 while (nextSon != firstSon) {
2075 helpQueue.pushBack(nextSon);
2076 holdSib = nextSon->getNextSib(oldSib);
2077 oldSib = nextSon;
2078 nextSon = holdSib;
2079 }
2080 }
2081 }
2082 if (!helpQueue.empty()) {
2083 checkNode = helpQueue.popFrontRet();
2084 if (checkNode->type() != PQNodeRoot::PQNodeType::Leaf) {
2085 secondTrace.pushBack(checkNode);
2086 }
2087 } else {
2088 checkNode = 0;
2089 }
2090 }
2091
2092
2094
2095 for (it = secondTrace.begin(); it.valid(); ++it) {
2096 checkNode = *it;
2097 if (checkNode->type() == PQNodeRoot::PQNodeType::PNode) {
2098 if (checkNode->m_referenceChild != 0) {
2099 firstSon = checkNode->m_referenceChild;
2100 os << " edge [\n";
2101 os << " source " << id[checkNode->m_identificationNumber] << "\n";
2102 os << " target " << id[firstSon->m_identificationNumber] << "\n";
2103 os << " ]\n"; // edge
2104
2105 if (firstSon->m_sibRight != 0) {
2106 nextSon = firstSon->m_sibRight;
2107 }
2108 while (nextSon != firstSon) {
2109 os << " edge [\n";
2110 os << " source " << id[checkNode->m_identificationNumber] << "\n";
2111 os << " target " << id[nextSon->m_identificationNumber] << "\n";
2112 os << " ]\n"; // edge
2113 nextSon = nextSon->m_sibRight;
2114 }
2115 }
2116 } else if (checkNode->type() == PQNodeRoot::PQNodeType::QNode) {
2117 oldSib = 0;
2118 holdSib = 0;
2119
2120 firstSon = checkNode->m_leftEndmost;
2121 lastSon = checkNode->m_rightEndmost;
2122
2123 os << " edge [\n";
2124 os << " source " << id[checkNode->m_identificationNumber] << "\n";
2125 os << " target " << id[lastSon->m_identificationNumber] << "\n";
2126 os << " ]\n"; // edge
2127 if (firstSon != lastSon) {
2128 nextSon = lastSon->getNextSib(oldSib);
2129 os << " edge [\n";
2130 os << " source " << id[checkNode->m_identificationNumber] << "\n";
2131 os << " target " << id[nextSon->m_identificationNumber] << "\n";
2132 os << " ]\n"; // edge
2133
2134 oldSib = lastSon;
2135 while (nextSon != firstSon) {
2136 holdSib = nextSon->getNextSib(oldSib);
2137 oldSib = nextSon;
2138 nextSon = holdSib;
2139 os << " edge [\n";
2140 os << " source " << id[checkNode->m_identificationNumber] << "\n";
2141 os << " target " << id[nextSon->m_identificationNumber] << "\n";
2142 os << " ]\n"; // edge
2143 }
2144 }
2145 }
2146 }
2147 os << "]\n"; // graph
2148}
2149
2150template<class T, class X, class Y>
2152 /* Variables:
2153 * - \a checkLeaf is a pointer to a various PQLeaf of the set of
2154 * elements that has to be reduced.
2155 * - \a checkNode is a pointer to a various node of the pertinent
2156 * subtree.
2157 * - \a pertLeafCount counts the number of pertinent leaves in the
2158 * PQ-tree. Since Reduce() takes care that every node knows the
2159 * number of pertinent leaves in its frontier, the root of the
2160 * pertinent subtree can be identified with the help of \a pertLeafCount.
2161 * - \a processNodes is a queue storing nodes of the pertinent
2162 * subtree that are considered to be reduced next. A node may be
2163 * reduced (and therefore is pushed on to \a processNodes) as soon as
2164 * all its pertinent children have been reduced.
2165 */
2166 int pertLeafCount = 0;
2167 Queue<PQNode<T, X, Y>*> processNodes;
2168
2169 /*
2170 * In a first step the pertinent leaves have to be identified in the tree
2171 * and are entered on to the queue [[processNodes]]. The identification of
2172 * the leaves can be done with the help of a pointer stored in every
2173 * [[PQLeafKey]] in constant time for every element.
2174 */
2176 for (it = leafKeys.begin(); it.valid(); ++it) {
2177 PQNode<T, X, Y>* checkLeaf = (*it)->nodePointer();
2179 checkLeaf->m_pertLeafCount = 1;
2180 processNodes.append(checkLeaf);
2181 pertLeafCount++;
2182 }
2183
2184 PQNode<T, X, Y>* checkNode = processNodes.top();
2185 while (checkNode != nullptr && processNodes.size() > 0) {
2186 checkNode = processNodes.pop();
2187
2188 if (checkNode->m_pertLeafCount < pertLeafCount) {
2189 /*
2190 * Application of the template matchings to a pointer [[checkNode]]
2191 * storing the adress of a node that is <b>not the root</b> of the
2192 * pertinent subtree. Before applying the template matchings to
2193 * [[checkNode]], some values of the parent of [[checkNode]] are
2194 * updated. The number of the parents pertinent children stored in
2195 * [[pertChildCount]] is count down by one. In case that
2196 * [[checkNode->m_parent->m_pertChildCount == 0]], we know that all
2197 * pertinent children of the parent have been processed. Since the
2198 * parent then is allowed to be processed as well,
2199 * [[checkNode->m_parent]] is stored in the queue [[processNodes]].
2200 */
2201 checkNode->m_parent->m_pertLeafCount =
2202 checkNode->m_parent->m_pertLeafCount + checkNode->m_pertLeafCount;
2203
2204 checkNode->m_parent->m_pertChildCount--;
2205 if (!checkNode->m_parent->m_pertChildCount) {
2206 processNodes.append(checkNode->m_parent);
2207 }
2208 if (!templateL1(checkNode, 0) && !templateP1(checkNode, 0) && !templateP3(checkNode)
2209 && !templateP5(checkNode) && !templateQ1(checkNode, 0)
2210 && !templateQ2(checkNode, 0)) {
2211 checkNode = nullptr;
2212 }
2213 } else {
2214 /*
2215 * application of the template matchings to a pointer [[checkNode]]
2216 * that stores the adress of a node that <b>is the root</b> of the
2217 * pertinent subtree. In a case that a template matching was
2218 * successfully applied, the pointer [[checkNode]] stores after the
2219 * application the adress of the root of pertinent subtree. This
2220 * includes nodes that have been newly introduced as root of the
2221 * pertinent subtree during the application. If no template matching
2222 * was successfully applied [[checkNode]] is a [[0]] pointer.
2223 */
2224 if (!templateL1(checkNode, 1) && !templateP1(checkNode, 1) && !templateP2(&checkNode)
2225 && !templateP4(&checkNode) && !templateP6(&checkNode) && !templateQ1(checkNode, 1)
2226 && !templateQ2(checkNode, 1) && !templateQ3(checkNode)) {
2227 checkNode = nullptr;
2228 }
2229 }
2230 }
2231
2232 m_pertinentRoot = checkNode;
2233 return m_pertinentRoot != nullptr;
2234}
2235
2236template<class T, class X, class Y>
2238 /* Reduction() calls the procedure Bubble() and if Bubble() was
2239 * successful, Reduction() calls the function Reduce().
2240 */
2241 bool success = Bubble(leafKeys);
2242
2243 if (!success) {
2244 return false;
2245 } else {
2246 return Reduce(leafKeys);
2247 }
2248}
2249
2250template<class T, class X, class Y>
2252 /*
2253 For every
2254 partial child we keep a set of pointers. Since there are at most
2255 two partial children, we initialize two sets. Every set contains
2256 besides a pointer to the partial child four pointers to its endmost
2257 children, sorted according to their full or empty labels and pointers
2258 to the immediate siblings of the partial child, also sorted according
2259 to their full or empty labels.
2260 */
2262 PQNode<T, X, Y>* partial_1 = nullptr;
2263
2264 /*
2265 Pointer to the full endmost child (more
2266 precisely: to the endmost child appearing on the full side) of
2267 [[partial_1]]. In case that ignored nodes are used, this [[endfull_1]]
2268 may store the adress of an ignored node.
2269 */
2270 PQNode<T, X, Y>* endfull_1 = nullptr;
2271
2272 /*
2273 Pointer to the empty endmost child (more
2274 precisely: to the endmost child appearing on the empty side) of
2275 [[partial_1]]. In case that ignored nodes are used, this [[endempty_1]]
2276 may store the adress of an ignored node.
2277 */
2278 PQNode<T, X, Y>* endempty_1 = nullptr;
2279
2280 /*
2281 Pointer to the first <i>non ignored</i> node
2282 with full status. [[realfull_1]] is identical to [[endfull_1]] if no
2283 ignored nodes appear at the full end of the first partial child.
2284 */
2285 PQNode<T, X, Y>* realfull_1 = nullptr;
2286
2287 /*
2288 Pointer to the first <i>non ignored</i> node
2289 with empty status. [[realempty_1]] is identical to [[endempty_1]] if no
2290 ignored nodes appear at the empty end of the first partial child.
2291 */
2292 PQNode<T, X, Y>* realempty_1 = nullptr;
2293
2294 // Pointer to the second partial child.
2295 PQNode<T, X, Y>* partial_2 = nullptr;
2296
2297 /*
2298 Pointer to the full endmost child (more
2299 precisely: to the endmost child appearing on the full side) of
2300 [[partial_2]]. In case that ignored nodes are used, this [[endfull_2]]
2301 may store the adress of an ignored node.
2302 */
2303 PQNode<T, X, Y>* endfull_2 = nullptr;
2304
2305 /*
2306 Pointer to the empty endmost child (more
2307 precisely: to the endmost child appearing on the empty side) of
2308 [[partial_2]]. In case that ignored nodes are used, this [[endempty_2]]
2309 may store the adress of an ignored node.
2310 */
2311 PQNode<T, X, Y>* endempty_2 = nullptr;
2312
2313 /*
2314 Pointer to the first <i>non ignored</i> node
2315 with empty status. [[realempty_2]] is identical to [[endempty_2]] if no
2316 ignored nodes appear at the empty end of the first partial child.
2317 */
2318 PQNode<T, X, Y>* realempty_2 = nullptr;
2319
2320 /*
2321 Pointer to a full sibling of
2322 [[partial_1]], if it exists. In case that ignored nodes are used
2323 this [[sibfull_1]] stores the direct sibling of [[partial_1]]
2324 on the side where the full siblings are. Hence [[sibfull_1]] may
2325 store an ignored node.
2326 */
2327 PQNode<T, X, Y>* sibfull_1 = nullptr;
2328
2329 /*
2330 Pointer to a partial sibling of
2331 [[partial_1]], if it exists. In case that ignored nodes are used
2332 this [[sibpartial_1]] stores the direct sibling of [[partial_1]]
2333 on the side where a partial sibling is. Hence [[sibpartial_1]] may
2334 store an ignored node.
2335 */
2336 PQNode<T, X, Y>* sibpartial_1 = nullptr;
2337
2338 /*
2339 Pointer to an empty sibling of
2340 [[parial_1]], if it exists. In case that ignored nodes are used
2341 this [[sibempty_1]] stores the direct sibling of [[partial_1]]
2342 on the side where the empty siblings are. Hence [[sibempty_1]] may
2343 store an ignored node.
2344 */
2345 PQNode<T, X, Y>* sibempty_1 = nullptr;
2346
2347 /*
2348 Pointer only used in case that [[partial_1]] has
2349 no non-ignored siblings on one side. [[partial_1]] then is endmost child
2350 of [[nodePtr]], but ignored children may appear between [[partial_1]]
2351 and the end of sequence of children of [[nodePtr]]. The
2352 [[nonstatussib_1]] then stores the adress of the endmost ignored child.
2353 Observe that it is not valid for a $Q$-node to have only one
2354 non-ignored child and several ignored children. Hence this situation
2355 is only allowed to appear <b>once</b> on one side of [[partial_1]].
2356 Every other situation results in an error message.
2357 */
2358 PQNode<T, X, Y>* nonstatussib_1 = nullptr;
2359
2360 /*
2361 Pointer to a full sibling of
2362 [[partial_2]], if it exists. In case that ignored nodes are used
2363 this [[sibfull_2]] stores the direct sibling of [[partial_2]]
2364 on the side where the full siblings are. Hence [[sibfull_2]] may
2365 store an ignored node.
2366 */
2367 PQNode<T, X, Y>* sibfull_2 = nullptr;
2368
2369 /*
2370 Pointer to a partial sibling of
2371 [[partial_2]], if it exists. In case that ignored nodes are used
2372 this [[sibpartial_2]] stores the direct sibling of [[partial_2]]
2373 on the side where a partial sibling is. Hence [[sibpartial_2]] may
2374 store an ignored node.
2375 */
2376 PQNode<T, X, Y>* sibpartial_2 = nullptr;
2377
2378 /*
2379 Pointer to an empty sibling of
2380 [[parial_2]], if it exists. In case that ignored nodes are used
2381 this [[sibempty_2]] stores the direct sibling of [[partial_2]]
2382 on the side where the empty siblings are. Hence [[sibempty_2]] may
2383 store an ignored node.
2384 */
2385 PQNode<T, X, Y>* sibempty_2 = nullptr;
2386
2387 /*
2388 Pointer only used in case that [[partial_2]] has
2389 no non-ignored siblings on one side. [[partial_2]] then is endmost child
2390 of [[nodePtr]], but ignored children may appear between [[partial_2]]
2391 and the end of sequence of children of [[nodePtr]]. The
2392 [[nonstatussib_2]] then stores the adress of the endmost ignored child.
2393 Observe that it is not valid for a $Q$-node to have only one
2394 non-ignored child and several ignored children. Hence this situation
2395 is only allowed to appear <b>once</b> on one side of [[partial_2]].
2396 Every other situation results in an error message.
2397 */
2398 PQNode<T, X, Y>* nonstatussib_2 = nullptr;
2399
2400 PQNode<T, X, Y>* helpptr = nullptr;
2401
2402 PQNode<T, X, Y>* checkVarLeft = nullptr;
2403
2404 PQNode<T, X, Y>* checkVarRight = nullptr;
2405
2406 /*
2407 [[endmostcheck]] is [[1]], if [[partial_1]] is the endmost
2408 child of [[nodePtr]]. Per default, [[endmostcheck]] is [[0]].
2409 */
2410 int endmostcheck = 0;
2411
2412
2414 if (!isRoot) {
2415 nodePtr->m_parent->partialChildren->pushFront(nodePtr);
2416 }
2417
2418 if (!nodePtr->partialChildren->empty()) { // Get a partial child.
2419 partial_1 = nodePtr->partialChildren->popFrontRet();
2420
2421 // Get the full and empty
2422 // endmost children of the
2423 // partial child [[partial_1]].
2424 checkVarLeft = clientLeftEndmost(partial_1);
2425 checkVarRight = clientRightEndmost(partial_1);
2426 if (checkVarLeft->status() == PQNodeRoot::PQNodeStatus::Full) {
2427 endfull_1 = partial_1->m_leftEndmost;
2428 realfull_1 = checkVarLeft;
2429 } else {
2430 // partial child with no full endmost child detected?
2432
2433 endfull_1 = partial_1->m_rightEndmost;
2434 realfull_1 = checkVarRight;
2435 }
2436
2437 if (checkVarLeft->status() == PQNodeRoot::PQNodeStatus::Empty) {
2438 endempty_1 = partial_1->m_leftEndmost;
2439 realempty_1 = checkVarLeft;
2440 } else {
2441 // partial child with no empty endmost child detected?
2443
2444 endempty_1 = partial_1->m_rightEndmost;
2445 realempty_1 = checkVarRight;
2446 }
2447
2448 // Get the immediate
2449 // siblings of the partial
2450 // child [[partial_1]].
2451 if (clientSibLeft(partial_1) != nullptr) {
2452 if (clientSibLeft(partial_1)->status() == PQNodeRoot::PQNodeStatus::Full) {
2453 sibfull_1 = partial_1->m_sibLeft;
2454 } else if (clientSibLeft(partial_1)->status() == PQNodeRoot::PQNodeStatus::Empty) {
2455 sibempty_1 = partial_1->m_sibLeft;
2456 } else if (clientSibLeft(partial_1)->status() == PQNodeRoot::PQNodeStatus::Partial) {
2457 sibpartial_1 = partial_1->m_sibLeft;
2458 }
2459 } else {
2460 nonstatussib_1 = partial_1->m_sibLeft;
2461 }
2462
2463 if (clientSibRight(partial_1) != nullptr) {
2464 if (clientSibRight(partial_1)->status() == PQNodeRoot::PQNodeStatus::Full) {
2465 sibfull_1 = partial_1->m_sibRight;
2466 } else if (clientSibRight(partial_1)->status() == PQNodeRoot::PQNodeStatus::Empty) {
2467 sibempty_1 = partial_1->m_sibRight;
2468 } else if (clientSibRight(partial_1)->status() == PQNodeRoot::PQNodeStatus::Partial) {
2469 sibpartial_1 = partial_1->m_sibRight;
2470 }
2471 } else {
2472 // partial child detected with no siblings of valid status?
2473 OGDF_ASSERT(nonstatussib_1 == nullptr);
2474 nonstatussib_1 = partial_1->m_sibRight;
2475 }
2476 }
2477
2478
2479 if (!nodePtr->partialChildren->empty()) { // There is a second partial child.
2480 partial_2 = nodePtr->partialChildren->popFrontRet();
2481 // Get the full and empty endmost
2482 // children of the partial
2483 // child [[partial_2]].
2484
2485 checkVarLeft = clientLeftEndmost(partial_2);
2486 checkVarRight = clientRightEndmost(partial_2);
2487 if (checkVarLeft->status() == PQNodeRoot::PQNodeStatus::Full) {
2488 endfull_2 = partial_2->m_leftEndmost;
2489 } else {
2490 // partial child with no full endmost child detected?
2492
2493 endfull_2 = partial_2->m_rightEndmost;
2494 }
2495
2496 if (checkVarLeft->status() == PQNodeRoot::PQNodeStatus::Empty) {
2497 endempty_2 = partial_2->m_leftEndmost;
2498 realempty_2 = checkVarLeft;
2499 } else {
2500 // partial child with no empty endmost child detected?
2502
2503 endempty_2 = partial_2->m_rightEndmost;
2504 realempty_2 = checkVarRight;
2505 }
2506 // Get the immediate siblings
2507 // of the partial child
2508 // [[partial_2]].
2509 if (clientSibLeft(partial_2) != nullptr) {
2510 if (clientSibLeft(partial_2)->status() == PQNodeRoot::PQNodeStatus::Full) {
2511 sibfull_2 = partial_2->m_sibLeft;
2512 } else if (clientSibLeft(partial_2)->status() == PQNodeRoot::PQNodeStatus::Empty) {
2513 sibempty_2 = partial_2->m_sibLeft;
2514 } else if (clientSibLeft(partial_2)->status() == PQNodeRoot::PQNodeStatus::Partial) {
2515 sibpartial_2 = partial_2->m_sibLeft;
2516 }
2517 } else {
2518 nonstatussib_2 = partial_2->m_sibLeft;
2519 }
2520
2521
2522 if (clientSibRight(partial_2) != nullptr) {
2523 if (clientSibRight(partial_2)->status() == PQNodeRoot::PQNodeStatus::Full) {
2524 sibfull_2 = partial_2->m_sibRight;
2525 } else if (clientSibRight(partial_2)->status() == PQNodeRoot::PQNodeStatus::Empty) {
2526 sibempty_2 = partial_2->m_sibRight;
2527 } else if (clientSibRight(partial_2)->status() == PQNodeRoot::PQNodeStatus::Partial) {
2528 sibpartial_2 = partial_2->m_sibRight;
2529 }
2530 } else {
2531 OGDF_ASSERT(nonstatussib_2 == nullptr);
2532 nonstatussib_2 = partial_2->m_sibRight;
2533 }
2534 }
2535
2536
2537 if (partial_1 != nullptr && partial_2 != nullptr)
2538
2539 /*
2540 Connect the endmost
2541 children of the partial children [[partial_1]] and [[partial_2]] correctly
2542 with their new siblings. In doing this, all children of the partial
2543 children become children of [[nodePtr]]. The reader should observe that
2544 the parent pointers of the interior children of [[partial_1]] and
2545 [[partial_2]] are not updated in order to hit the linear time complexity.
2546
2547 When including the children of the partial children to the children
2548 of [[nodePtr]], it is taken care that all full children
2549 form a consecutive sequence afterwards. If neccessary the pointers to the
2550 endmost children of [[nodePtr]] are updated.
2551 */
2552 {
2553 if (sibfull_1 != nullptr && sibfull_2 != nullptr)
2554 // There are full children between
2555 // the 2 partial nodes.
2556 // Connect the full children
2557 // between the 2 partial children
2558 // with the full endmost children
2559 // of the 2 partial nodes.
2560 {
2561 sibfull_1->changeSiblings(partial_1, endfull_1);
2562 endfull_1->putSibling(sibfull_1);
2563 sibfull_2->changeSiblings(partial_2, endfull_2);
2564 endfull_2->putSibling(sibfull_2);
2565 }
2566
2567 else if (sibpartial_1 != nullptr && sibpartial_2 != nullptr)
2568 // There are no full children between
2569 // the 2 partial nodes. Connect the
2570 // full endmost children of the
2571 // partial nodes as siblings.
2572 {
2573 if (partial_1 == sibpartial_2 && partial_2 == sibpartial_1)
2574 // Regular Case.
2575 {
2576 endfull_1->putSibling(endfull_2);
2577 endfull_2->putSibling(endfull_1);
2578 }
2579 // Only ignored children between
2580 // partial_1 and partial_2.
2581 else {
2582 endfull_1->putSibling(sibpartial_1);
2583 sibpartial_1->changeSiblings(partial_1, endfull_1);
2584 endfull_2->putSibling(sibpartial_2);
2585 sibpartial_2->changeSiblings(partial_2, endfull_2);
2586 }
2587 }
2588 // Include the children of the
2589 // partial children with their
2590 // full nodes inbetween into
2591 // the sequence of the children of
2592 // Q-node nodePtr.
2593 if (sibempty_1 == nullptr)
2594 // partial_1 is endmost child of
2595 // nodePtr. Make the empty endmost
2596 // child of partial_1 be the new
2597 // endmost child of nodePtr.
2598 {
2599 if (nonstatussib_1 == nullptr)
2600 // Regular case.
2601 {
2602 nodePtr->changeEndmost(partial_1, endempty_1);
2603 } else
2604 // Only ignored children between
2605 // partial_1 and one end of nodePtr.
2606 {
2607 nonstatussib_1->changeSiblings(partial_1, endempty_1);
2608 endempty_1->putSibling(nonstatussib_1);
2609 }
2610 endempty_1->m_parent = nodePtr;
2611 realempty_1->m_parent = nodePtr;
2612 }
2613
2614 else
2615 // partial_1 is not endmost child.
2616 {
2617 sibempty_1->changeSiblings(partial_1, endempty_1);
2618 endempty_1->putSibling(sibempty_1);
2619 }
2620
2621
2622 if (sibempty_2 == nullptr)
2623 // partial_2 is endmost child of
2624 // nodePtr. Make the empty endmost
2625 // child of partial_2 be the new
2626 // endmost child of nodePtr.
2627 {
2628 if (nonstatussib_2 == nullptr)
2629 // Regular case.
2630 {
2631 nodePtr->changeEndmost(partial_2, endempty_2);
2632 } else
2633 // Only ignored children between
2634 // partial_1 and one end of
2635 // nodePtr.
2636 {
2637 nonstatussib_2->changeSiblings(partial_2, endempty_2);
2638 endempty_2->putSibling(nonstatussib_2);
2639 }
2640 endempty_2->m_parent = nodePtr;
2641 realempty_2->m_parent = nodePtr;
2642 }
2643
2644 else
2645 // partial_2 is not endmost child.
2646 {
2647 sibempty_2->changeSiblings(partial_2, endempty_2);
2648 endempty_2->putSibling(sibempty_2);
2649 }
2650
2651 // Copy the full children of
2652 // partial_1 and partial_2 to
2653 // nodePtr.
2654 while (!partial_2->fullChildren->empty()) {
2655 helpptr = partial_2->fullChildren->popFrontRet();
2656 nodePtr->fullChildren->pushFront(helpptr);
2657 }
2658 nodePtr->m_childCount = nodePtr->m_childCount + partial_2->m_childCount - 1;
2659
2660 destroyNode(partial_2);
2661
2662 while (!partial_1->fullChildren->empty()) {
2663 helpptr = partial_1->fullChildren->popFrontRet();
2664 nodePtr->fullChildren->pushFront(helpptr);
2665 }
2666 nodePtr->m_childCount = nodePtr->m_childCount + partial_1->m_childCount - 1;
2667
2668 destroyNode(partial_1);
2669 }
2670
2671
2672 else if (partial_1 != nullptr)
2673
2674 /*
2675 Connect the endmost
2676 children of the partial child [[partial_1]] correctly
2677 with their new siblings. In doing this, all children of the partial
2678 child become children of [[nodePtr]]. The reader should observe that
2679 the parent pointers of the interior children of [[partial_1]]
2680 are not updated in order to hit the linear time complexity.
2681
2682 When including the children of [[partial_1]] to the children
2683 of [[nodePtr]], it is taken care that all full children
2684 form a consecutive sequence afterwards. If necessary the pointers to the
2685 endmost children of [[nodePtr]] are updated.
2686 */
2687 {
2688 if ((clientLeftEndmost(nodePtr) == partial_1) || (clientRightEndmost(nodePtr) == partial_1)) {
2689 // partial_1 is endmost child.
2690 endmostcheck = 1;
2691 }
2692
2693 if (sibfull_1 != nullptr)
2694 // There are full children on one
2695 // side of the partial node.
2696 // Connect the full children with
2697 // the full endmost child of
2698 // partial_1.
2699 {
2700 sibfull_1->changeSiblings(partial_1, endfull_1);
2701 endfull_1->putSibling(sibfull_1);
2702 }
2703
2704 else if (!endmostcheck)
2705 // There are not any full children
2706 // and partial_1 is not endmost.
2707 // So get the 2nd empty sibling
2708 // of partial_1 and connect it
2709 // to the full endmost child
2710 // of partial_1.
2711 {
2712 if (partial_1->m_sibLeft != sibempty_1) {
2713 sibempty_2 = partial_1->m_sibLeft;
2714 } else {
2715 sibempty_2 = partial_1->m_sibRight;
2716 }
2717
2718 sibempty_2->changeSiblings(partial_1, endfull_1);
2719 endfull_1->putSibling(sibempty_2);
2720 }
2721
2722 else
2723 // partial_1 is endmost child
2724 // and there are no full children.
2725 // Make the full endmost child of
2726 // partial_1 be the endmostchild
2727 // of nodePtr.
2728 {
2729 if (nonstatussib_1 == nullptr)
2730 // Regular case.
2731 {
2732 nodePtr->changeEndmost(partial_1, endfull_1);
2733 } else
2734 // Only ignored children between
2735 // partial_1 and one end of
2736 // nodePtr.
2737 {
2738 nonstatussib_1->changeSiblings(partial_1, endfull_1);
2739 endfull_1->putSibling(nonstatussib_1);
2740 }
2741 endfull_1->m_parent = nodePtr;
2742 realfull_1->m_parent = nodePtr;
2743 }
2744
2745 if (sibempty_1 == nullptr)
2746 // There are no empty children.
2747 // partial_1 is endmost child of
2748 // nodePtr. Make the empty endmost
2749 // child of partial_1 be the new
2750 // endmost child of nodePtr.
2751 {
2752 if (nonstatussib_1 == nullptr)
2753 // Regular case.
2754 {
2755 nodePtr->changeEndmost(partial_1, endempty_1);
2756 } else
2757 // Only ignored children between
2758 // partial_1 and one end of
2759 // nodePtr.
2760 {
2761 nonstatussib_1->changeSiblings(partial_1, endempty_1);
2762 endempty_1->putSibling(nonstatussib_1);
2763 }
2764 endempty_1->m_parent = nodePtr;
2765 realempty_1->m_parent = nodePtr;
2766 }
2767
2768 else
2769 // There are empty children. So
2770 // connect the empty endmost child
2771 // of partial_1 with sibempty_1.
2772 {
2773 sibempty_1->changeSiblings(partial_1, endempty_1);
2774 endempty_1->putSibling(sibempty_1);
2775 }
2776
2777 while (!partial_1->fullChildren->empty()) {
2778 helpptr = partial_1->fullChildren->popFrontRet();
2779 nodePtr->fullChildren->pushFront(helpptr);
2780 }
2781
2782 nodePtr->m_childCount = nodePtr->m_childCount + partial_1->m_childCount - 1;
2783 destroyNode(partial_1);
2784 }
2785 // else nodePtr does not have partial children. Then nothing is to do.
2786}
2787
2788template<class T, class X, class Y>
2790 if (nodePtr->m_referenceParent != nullptr) {
2791 /*
2792 Checksif [[nodePtr]] is connected with its parent via the reference
2793 pointers (see \ref{PQNode}). If so, the next sibling of [[nodePtr]]
2794 will be the the new reference child.
2795 */
2796 nodePtr->m_referenceParent->m_referenceChild = nodePtr->m_sibRight;
2797 nodePtr->m_sibRight->m_referenceParent = nodePtr->m_referenceParent;
2798 if (nodePtr->m_referenceParent->m_referenceChild == nodePtr) {
2799 nodePtr->m_referenceParent->m_referenceChild = nullptr;
2800 }
2801 nodePtr->m_referenceParent = nullptr;
2802 } else if (nodePtr->endmostChild()) {
2803 /*
2804 Check if [[nodePtr]] is the endmost child of a $Q$-node.
2805 If so, the next sibling of [[nodePtr]] will be the the new endmost
2806 child of the $Q$-node. Observe that the sibling then gets a valid
2807 pointer to its parent.
2808 */
2809 PQNode<T, X, Y>* sibling = nodePtr->getNextSib(nullptr);
2810 if (nodePtr->m_parent->m_leftEndmost == nodePtr) {
2811 nodePtr->m_parent->m_leftEndmost = sibling;
2812 } else if (nodePtr->m_parent->m_rightEndmost == nodePtr) {
2813 nodePtr->m_parent->m_rightEndmost = sibling;
2814 }
2815 if (sibling != nullptr) {
2816 sibling->m_parent = nodePtr->m_parent;
2817 }
2818 }
2819
2820 /*
2821 Remove [[nodePtr]] from its immediate siblings and links the
2822 siblings via the [[sibRight]] and [[sibLeft]] pointers.
2823 */
2824 if (nodePtr->m_sibRight != nullptr && nodePtr->m_sibRight != nodePtr) {
2825 if (nodePtr->m_sibRight->m_sibLeft == nodePtr) {
2826 nodePtr->m_sibRight->m_sibLeft = nodePtr->m_sibLeft;
2827 } else {
2828 // Sibling was not connected to child?
2829 OGDF_ASSERT(nodePtr->m_sibRight->m_sibRight == nodePtr);
2830 nodePtr->m_sibRight->m_sibRight = nodePtr->m_sibLeft;
2831 }
2832 }
2833 if (nodePtr->m_sibLeft != nullptr && nodePtr->m_sibLeft != nodePtr) {
2834 if (nodePtr->m_sibLeft->m_sibRight == nodePtr) {
2835 nodePtr->m_sibLeft->m_sibRight = nodePtr->m_sibRight;
2836 } else {
2837 // Sibling was not connected to child?
2838 OGDF_ASSERT(nodePtr->m_sibLeft->m_sibLeft == nodePtr);
2839 nodePtr->m_sibLeft->m_sibLeft = nodePtr->m_sibRight;
2840 }
2841 }
2842
2843 nodePtr->m_sibRight = nullptr;
2844 nodePtr->m_sibLeft = nullptr;
2845}
2846
2847template<class T, class X, class Y>
2849 if (parent != nullptr) {
2850 removeChildFromSiblings(child);
2851 parent->m_childCount--;
2854 parent->m_pertChildCount--;
2855 }
2856 return parent->m_childCount;
2857 } else {
2858 //parent is invalid 0-pointer.
2859 return -1;
2860 }
2861}
2862
2863template<class T, class X, class Y>
2864void PQTree<T, X, Y>::sortExceptions(int Exceptions[], int arraySize) {
2865 bool changed = true;
2866 while (changed) {
2867 changed = false;
2868 for (int i = 0; i < (arraySize - 1); i++) {
2869 if (Exceptions[i] > Exceptions[i + 1]) {
2870 std::swap(Exceptions[i], Exceptions[i + 1]);
2871 changed = true;
2872 }
2873 }
2874 }
2875}
2876
2877template<class T, class X, class Y>
2879 if (nodePtr->type() == PQNodeRoot::PQNodeType::Leaf
2880 && nodePtr->status() == PQNodeRoot::PQNodeStatus::Full) {
2881 if (!isRoot) {
2882 nodePtr->m_parent->fullChildren->pushFront(nodePtr);
2883 }
2884 return true;
2885 }
2886
2887 return false;
2888}
2889
2890template<class T, class X, class Y>
2892 if (nodePtr->type() != PQNodeRoot::PQNodeType::PNode
2893 || nodePtr->fullChildren->size() != nodePtr->m_childCount) {
2894 return false;
2895 } else {
2897 if (!isRoot) {
2898 nodePtr->m_parent->fullChildren->pushFront(nodePtr);
2899 }
2900
2901 return true;
2902 }
2903}
2904
2905template<class T, class X, class Y>
2907 if ((*nodePtr)->type() != PQNodeRoot::PQNodeType::PNode
2908 || (*nodePtr)->partialChildren->size() > 0) {
2909 return false;
2910 }
2911
2912 (*nodePtr)->m_childCount = (*nodePtr)->m_childCount - (*nodePtr)->fullChildren->size() + 1;
2913 // Gather all full children of nodePtr
2914 // as children of the new P-node.
2915 // Delete them from nodePtr.
2916
2917 PQNode<T, X, Y>* newNode = createNodeAndCopyFullChildren((*nodePtr)->fullChildren);
2918 // Correct parent-pointer and
2919 // sibling-pointers of the new P-node.
2920
2921 newNode->m_parent = (*nodePtr);
2922 newNode->m_sibRight = (*nodePtr)->m_referenceChild->m_sibRight;
2923 newNode->m_sibLeft = newNode->m_sibRight->m_sibLeft;
2924 newNode->m_sibLeft->m_sibRight = newNode;
2925 newNode->m_sibRight->m_sibLeft = newNode;
2927 // The new P-node now is the root of
2928 // the pertinent subtree.
2929 (*nodePtr) = newNode;
2930
2931 return true;
2932}
2933
2934template<class T, class X, class Y>
2936 /* Variables:
2937 * - \p newPnode is the pointer to the new P-node, or, in case
2938 * that \p nodePtr has only one full child, is the pointer of this child.
2939 * - \p newQnode is the pointer to the new Q-node.
2940 * - \p newNode is used for the proper allocation of the new
2941 * Q-node.
2942 * - \p emptyNode is a pointer to any empty child of \p nodePtr.
2943 */
2944 if (nodePtr->type() != PQNodeRoot::PQNodeType::PNode || nodePtr->partialChildren->size() > 0) {
2945 return false;
2946 }
2947
2948 /*
2949 Create a new partial $Q$-node stored in [[newQnode]].
2950 It replaces [[nodePtr]] by the Q-node [[newQnode]] in the $PQ$-tree
2951 and makes [[nodePtr]] endmost child of [[newQnode]].
2952 This is done by updating parent-pointers and sibling-pointers.
2953 */
2954 PQInternalNode<T, X, Y>* newNode = new PQInternalNode<T, X, Y>(m_identificationNumber++,
2956 PQNode<T, X, Y>* newQnode = newNode;
2957 m_pertinentNodes->pushFront(newQnode);
2958
2959 exchangeNodes(nodePtr, newQnode);
2960 nodePtr->m_parent = newQnode;
2962
2963 newQnode->m_leftEndmost = (nodePtr);
2964 newQnode->m_childCount = 1;
2965
2966 /*
2967 Create a new full $P$-node stored in [[newPnode]].
2968 It copies the full children of [[nodePtr]] to [[newPnode]].
2969 The new $P$-node will then be included into the tree as child of
2970 the new $Q$-node [[newQnode]].
2971 */
2972 if (nodePtr->fullChildren->size() > 0) {
2973 nodePtr->m_childCount = nodePtr->m_childCount - nodePtr->fullChildren->size();
2974
2975 PQNode<T, X, Y>* newPnode = createNodeAndCopyFullChildren(nodePtr->fullChildren);
2977
2978 // Update newQnode.
2979 newQnode->m_childCount++;
2980 newQnode->fullChildren->pushFront(newPnode);
2981 // Update sibling pointers.
2982 nodePtr->m_sibRight = newPnode;
2983 newPnode->m_sibLeft = nodePtr;
2984 newQnode->m_rightEndmost = newPnode;
2985 newPnode->m_parent = newQnode;
2986 }
2987
2988 // Check if nodePtr contains
2989 // only one son. If so, nodePtr
2990 // will be deleted from the tree.
2991 PQNode<T, X, Y>* emptyNode = nodePtr->m_referenceChild;
2992 checkIfOnlyChild(emptyNode, nodePtr);
2993 // Update partialchildren stack of
2994 // the parent of the new Q-node.
2995 newQnode->m_parent->partialChildren->pushFront(newQnode);
2996
2997 return true;
2998}
2999
3000template<class T, class X, class Y>
3002 if ((*nodePtr)->type() != PQNodeRoot::PQNodeType::PNode
3003 || (*nodePtr)->partialChildren->size() != 1) {
3004 return false;
3005 }
3006
3007 PQNode<T, X, Y>* partialChild = (*nodePtr)->partialChildren->popFrontRet();
3008 copyFullChildrenToPartial(*nodePtr, partialChild);
3009 // If nodePtr does not have any
3010 // empty children, then it has to
3011 // be deleted and the partial node
3012 // is occupying its place in the tree.
3013 checkIfOnlyChild(partialChild, *nodePtr);
3014 // The partial child now is
3015 // root of the pertinent subtree.
3016 *nodePtr = partialChild;
3017
3018 return true;
3019}
3020
3021template<class T, class X, class Y>
3023 /* Variables:
3024 * - \a partialChild is a pointer to the partial child of
3025 * \a nodePtr.
3026 * - \a checkNode is a pointer to the endmost empty child of
3027 * \a partialChild.
3028 * - \a emptyNode is a pointer to the empty node that is copied as
3029 * endmost child to \a partialChild.
3030 * - \a emptyChildCount stores the number of empty children of
3031 * \a nodePtr.
3032 *
3033 * If neccessary, the function templateP5() creates a new full P-node
3034 * and copies all full children of \p nodePtr to this new full P-node.
3035 * All empty children of \p nodePtr stay empty children of \p nodePtr.
3036 *
3037 * The new full P-node and \p nodePtr will be the new endmost children of
3038 * \a partialChild. The \a partialChild then occupies the position
3039 * of \p nodePtr in the PQ-tree.
3040 */
3041 if ((nodePtr->type() != PQNodeRoot::PQNodeType::PNode)
3042 || (nodePtr->partialChildren->size() != 1)) {
3043 return false;
3044 }
3045
3046 /*
3047 Remove [[partialChild]] from the children of [[nodePtr]]. The node
3048 [[partialChild]] then occupies the position of [[nodePtr]] in the
3049 $PQ$-tree which is done in the function call [[exchangeNodes]]
3050 (\ref{exchangeNodes}). The chunk then removes all full children from
3051 [[nodePtr]] and adds them as children of a new $P$-node as endmost
3052 child of [[partialChild]]. This is done in the function call
3053 [[copyFullChildrenToPartial]] (\ref{copyFullChildrenToPartial}).
3054 When this chunk has finished, [[nodePtr]] has only empty children.
3055 */
3056 int emptyChildCount = nodePtr->m_childCount - nodePtr->fullChildren->size() - 1;
3057 PQNode<T, X, Y>* partialChild = nodePtr->partialChildren->popFrontRet();
3058 nodePtr->m_parent->partialChildren->pushFront(partialChild);
3059 removeChildFromSiblings(partialChild);
3060 exchangeNodes(nodePtr, partialChild);
3061 copyFullChildrenToPartial(nodePtr, partialChild);
3062
3063 if (emptyChildCount > 0) {
3064 /*
3065 Check if [[nodePtr]] has just one empty child. If so, the child
3066 is stored in [[emptyNode]] in order to be added to the empty
3067 side of the partial $Q$-node [[partialChild]]. If [[nodePtr]]
3068 has more than one empty child, [[nodePtr]] is stored in
3069 [[emptyNode]] in order to be added to the empty
3070 side of the partial $Q$-node [[partialChild]].
3071 */
3072 PQNode<T, X, Y>* emptyNode;
3073 if (emptyChildCount == 1) {
3074 emptyNode = nodePtr->m_referenceChild;
3075 removeChildFromSiblings(emptyNode);
3076
3077 } else {
3078 emptyNode = nodePtr;
3079 emptyNode->m_childCount = emptyChildCount;
3080 }
3081
3082 /*
3083 Check at which side of [[partialChild]]
3084 the empty children hide. [[emptyNode]] stores the empty node
3085 that is added to the empty side of [[partialChild]].
3086 */
3087 PQNode<T, X, Y>* checkNode;
3088 if (clientLeftEndmost(partialChild)->status() == PQNodeRoot::PQNodeStatus::Empty) {
3089 checkNode = partialChild->m_leftEndmost;
3090 partialChild->m_leftEndmost = emptyNode;
3091 } else {
3092 // Endmostchild not found?
3094 clientRightEndmost(partialChild)->status() == PQNodeRoot::PQNodeStatus::Empty);
3095
3096 checkNode = partialChild->m_rightEndmost;
3097 partialChild->m_rightEndmost = emptyNode;
3098 }
3099
3100 linkChildrenOfQnode(checkNode, emptyNode);
3101 emptyNode->m_parent = partialChild;
3103 partialChild->m_childCount++;
3104 }
3105 // If nodePtr did not have any empty
3106 // children it has to be deleted.
3107 if (emptyChildCount <= 1) {
3108 destroyNode(nodePtr);
3109 }
3110
3111 return true;
3112}
3113
3114template<class T, class X, class Y>
3116 /* Variables:
3117 * - \a partial_1 is a pointer to the first partial child of
3118 * \p nodePtr.
3119 * - \a partial_2 is a pointer to the second partial child of
3120 * \p nodePtr.
3121 * - \a fullEnd_1 is a pointer to a full endmost child of \a partial_1.
3122 * - \a fullEnd_2 is a pointer to a full endmost child of \a partial_2.
3123 * - \a emptyEnd_2 is a pointer to the empty endmost child (more
3124 * precisely: to the endmost child appearing on the empty side) of
3125 * \a partial_2. In case that <em>ignored nodes</em> are used, this
3126 * \a emptyEnd_2 may store the adress of an ignored node.
3127 * - \a realEmptyEnd_2 is a pointer to the first <em>non ignored</em>
3128 * node with empty status on the empty side of \a partial_2. In case
3129 * that no ignored nodes are used, \a realEmpty_2 is identical to
3130 * \a endEmpty_2.
3131 */
3132#if 0
3133 PQNode<T,X,Y> *partial_1 = 0;
3134 PQNode<T,X,Y> *partial_2 = 0;
3135 PQNode<T,X,Y> *fullEnd_1 = 0;
3136 PQNode<T,X,Y> *fullEnd_2 = 0;
3137 PQNode<T,X,Y> *emptyEnd_2 = 0;
3138 PQNode<T,X,Y> *realEmptyEnd_2 = 0;
3139#endif
3140
3141 if ((*nodePtr)->type() != PQNodeRoot::PQNodeType::PNode
3142 || (*nodePtr)->partialChildren->size() != 2) {
3143 return false;
3144 }
3145
3146 /*
3147 Get the partial children of [[nodePtr]] and removes the second
3148 partial child stored in [[partial_2]] from the children of
3149 [[nodePtr]]. If there are any full children of [[nodePtr]], the
3150 chunk removes them from the children of [[nodePtr]] and copies them
3151 as children to a new $P$-node. This new $P$-node is then made
3152 endmost child of [[partial_1]].
3153 */
3154 PQNode<T, X, Y>* partial_1 = (*nodePtr)->partialChildren->popFrontRet();
3155 PQNode<T, X, Y>* partial_2 = (*nodePtr)->partialChildren->popFrontRet();
3156
3157 removeChildFromSiblings(partial_2);
3158 (*nodePtr)->m_childCount--;
3159 copyFullChildrenToPartial(*nodePtr, partial_1);
3160
3161 /*
3162 Check the endmost children of the two partial children of [[nodePtr]]
3163 and stores them at approriate places, remembering what kind of type
3164 the endmost children are.
3165 */
3166 PQNode<T, X, Y>* fullEnd_1;
3167 if (clientLeftEndmost(partial_1)->status() == PQNodeRoot::PQNodeStatus::Full) {
3168 fullEnd_1 = partial_1->m_leftEndmost;
3169 } else {
3170 // partial child with no Full endmost child detected?
3171 OGDF_ASSERT(clientRightEndmost(partial_1)->status() == PQNodeRoot::PQNodeStatus::Full);
3172 fullEnd_1 = partial_1->m_rightEndmost;
3173 }
3174
3175 PQNode<T, X, Y>* fullEnd_2 = nullptr;
3176 PQNode<T, X, Y>* emptyEnd_2 = nullptr;
3177 PQNode<T, X, Y>* realEmptyEnd_2 = nullptr;
3178 if (clientLeftEndmost(partial_2)->status() == PQNodeRoot::PQNodeStatus::Full) {
3179 fullEnd_2 = partial_2->m_leftEndmost;
3180 } else {
3181 // partial child with no Full or Empty endmost child detected?
3182 OGDF_ASSERT(clientLeftEndmost(partial_2)->status() == PQNodeRoot::PQNodeStatus::Empty);
3183
3184 emptyEnd_2 = partial_2->m_leftEndmost;
3185 realEmptyEnd_2 = clientLeftEndmost(partial_2);
3186 }
3187
3188 if (clientRightEndmost(partial_2)->status() == PQNodeRoot::PQNodeStatus::Full) {
3189 fullEnd_2 = partial_2->m_rightEndmost;
3190 } else {
3191 // partial child with no Full or Empty endmost child detected?
3192 OGDF_ASSERT(clientRightEndmost(partial_2)->status() == PQNodeRoot::PQNodeStatus::Empty);
3193
3194 emptyEnd_2 = partial_2->m_rightEndmost;
3195 realEmptyEnd_2 = clientRightEndmost(partial_2);
3196 }
3197
3198 OGDF_ASSERT(emptyEnd_2 != nullptr);
3199 OGDF_ASSERT(fullEnd_2 != emptyEnd_2);
3200 //partial child with same type of endmost child detected
3201
3202 /*
3203 The children of [[partial_2]] are removed from their parent and
3204 added as children to [[partial_1]]. This is done by resetting the
3205 sibling pointers of the two endmost children of [[partial_1]] and
3206 [[partial_2]] and the endmost child pointers of [[partial_1]].
3207 Observe that the parent pointers are not updated. The node
3208 [[partial_2]] is deleted.
3209 */
3210 while (!partial_2->fullChildren->empty()) {
3211 partial_1->fullChildren->pushFront(partial_2->fullChildren->popFrontRet());
3212 }
3213 linkChildrenOfQnode(fullEnd_1, fullEnd_2);
3214 if (partial_1->m_leftEndmost == fullEnd_1) {
3215 partial_1->m_leftEndmost = emptyEnd_2;
3216 } else {
3217 partial_1->m_rightEndmost = emptyEnd_2;
3218 }
3219
3220 emptyEnd_2->m_parent = partial_1;
3222
3223 realEmptyEnd_2->m_parent = partial_1;
3225
3226 partial_1->m_childCount = partial_1->m_childCount + partial_2->m_childCount;
3227 destroyNode(partial_2);
3228
3229 // If nodePtr does not have any
3230 // empty children, then it has to
3231 // be deleted and the partial node
3232 // is occupying its place in the tree.
3233 checkIfOnlyChild(partial_1, *nodePtr);
3234 // partial_1 is now root of the
3235 // pertinent subtree.
3236 *nodePtr = partial_1;
3237
3238 return true;
3239}
3240
3241template<class T, class X, class Y>
3243 if (nodePtr->type() == PQNodeRoot::PQNodeType::QNode && nodePtr != m_pseudoRoot
3244 && clientLeftEndmost(nodePtr)->status() == PQNodeRoot::PQNodeStatus::Full
3245 && clientRightEndmost(nodePtr)->status() == PQNodeRoot::PQNodeStatus::Full) {
3246 PQNode<T, X, Y>* seqStart = nullptr;
3247 PQNode<T, X, Y>* seqEnd = nullptr;
3248 if (checkChain(nodePtr, clientLeftEndmost(nodePtr), &seqStart, &seqEnd)) {
3250 if (!isRoot) {
3251 nodePtr->m_parent->fullChildren->pushFront(nodePtr);
3252 }
3253 return true;
3254 }
3255 }
3256
3257 return false;
3258}
3259
3260template<class T, class X, class Y>
3262 /* Variables:
3263 * - \a fullNode is a pointer to the full endmost child of \p nodePtr.
3264 * - \a sequenceBegin is a pointer to the first node of the
3265 * sequence of full children. Identical to the node fullNode and
3266 * mainly needed by the function checkChain().
3267 * - \a sequenceEnd is a pointer to the last node of the sequence
3268 * of full children. Is set by the function checkChain().
3269 * - \a partialChild is a pointer to the partial child of \p nodePtr.
3270 * - \a sequenceCons is 1 if all full children of
3271 * \p nodePtr form a consecutive sequence with one full child beeing
3272 * an endmost child of \p nodePtr \b and the partial child is
3273 * adjacent to the sequence.
3274 *
3275 * templateQ2() first checks if one of the above mentioned cases
3276 * occures and
3277 * then applies the necessary template matching.
3278 * No special action has to be performed for the full nodes. If there exists
3279 * a partial child that will be stored in \a partialChild, its children
3280 * are made children of \p nodePtr. So to say, \a partialChild is lifted
3281 * up to the Q-node \p nodePtr and the occurance of the children
3282 * of \a partialChild is fixed within the children of \p nodePtr.
3283 * (Remember that a partial child is also a Q-node).
3284 */
3285 if (nodePtr->type() != PQNodeRoot::PQNodeType::QNode || nodePtr->partialChildren->size() > 1) {
3286 return false;
3287 }
3288
3289 bool sequenceCons = false;
3290 if (nodePtr->fullChildren->size() > 0) {
3291 /*
3292 Get a full endmost child of
3293 the $Q$-node [[nodePtr]] if there exists one.
3294 */
3295 PQNode<T, X, Y>* fullNode = nullptr;
3296 if (nodePtr->m_leftEndmost != nullptr) {
3297 fullNode = clientLeftEndmost(nodePtr);
3298 if (fullNode->status() != PQNodeRoot::PQNodeStatus::Full) {
3299 fullNode = nullptr;
3300 }
3301 }
3302 if (nodePtr->m_rightEndmost != nullptr && fullNode == nullptr) {
3303 fullNode = clientRightEndmost(nodePtr);
3304 if (fullNode->status() != PQNodeRoot::PQNodeStatus::Full) {
3305 fullNode = nullptr;
3306 }
3307 }
3308
3309 /*
3310 In case that a full endmost child of [[nodePtr]] exists, this
3311 child has been stored in [[fullNode]] and the chunk checks by
3312 calling the function [[checkChain]] (\ref{checkChain}), if all
3313 full children of [[nodePtr]] form a consecutive sequence.
3314 In case that the full children
3315 of [[nodePtr]] form a consecutive sequence the
3316 return value of [[checkChain]] is [[1]]. If a partial child
3317 stored in [[partialChild]] exists, the chunk checks if
3318 [[partialChild]] is adjacent to the sequence of full children.
3319 If the latter case is [[1]], the flag [[sequenceCons]] is
3320 set to [[1]] and the function [[templateQ2]] is allowed to
3321 reduce the pertient children of [[nodePtr]].
3322 */
3323 PQNode<T, X, Y>* sequenceBegin = nullptr;
3324 PQNode<T, X, Y>* sequenceEnd = nullptr;
3325 if (fullNode != nullptr) {
3326 sequenceCons = checkChain(nodePtr, fullNode, &sequenceBegin, &sequenceEnd);
3327 }
3328
3329 if (sequenceCons && nodePtr->partialChildren->size() == 1) {
3330 PQNode<T, X, Y>* partialChild = nodePtr->partialChildren->front();
3331 sequenceCons = false;
3332
3333 if (clientSibLeft(sequenceEnd) == partialChild
3334 || clientSibRight(sequenceEnd) == partialChild) {
3335 sequenceCons = true;
3336 }
3337 }
3338 } else {
3339 if (!nodePtr->partialChildren->empty()) {
3340 /*
3341 If the $Q$-node [[nodePtr]] has no full children but one
3342 partial child this chunk checks, if the partial child is
3343 endmost child of the [[nodePtr]]. If this is not the case,
3344 [[nodePtr]] cannot be reduced by the template matching
3345 <b>Q2</b>.
3346 */
3347#if 0
3348 nodePtr->partialChildren->startAtBottom();
3349 partialChild = nodePtr->partialChildren->readNext();
3350#endif
3351 PQNode<T, X, Y>* partialChild = nodePtr->partialChildren->front();
3352 if ((clientLeftEndmost(nodePtr) == partialChild)
3353 || (clientRightEndmost(nodePtr) == partialChild)) {
3354 sequenceCons = true;
3355 }
3356 }
3357 }
3358
3359 if (sequenceCons) {
3360 removeBlock(nodePtr, isRoot);
3361 }
3362
3363 return sequenceCons;
3364}
3365
3366template<class T, class X, class Y>
3368 /* Variables:
3369 * - \a fullChild is a pointer to an arbitrary full child of \p nodePtr.
3370 * - \a fullStart is a pointer to the first full child of a
3371 * consecutive sequence of full children.
3372 * - \a fullEnd is a pointer to the last full child of a
3373 * consecutive sequence of full children.
3374 * - \a partial_1 is a pointer to the first partial child of \p nodePtr.
3375 * - \a partial_2 is a pointer to the second partial child of \p nodePtr.
3376 * - \a conssequence is 1 if the pertinent children of
3377 * \p nodePtr form a consecutive sequence with at most one partial
3378 * child at every end of the sequence.
3379 * - \a found is a help variable.
3380 *
3381 * templateQ3() first checks if one of the above mentioned cases
3382 * occures and then applies the neccessary template matching.
3383 * No special action has to be performed for the full nodes. If there exist
3384 * one or two partial children which will be stored in \a partial_1
3385 * or \a partial_2, their children
3386 * are made children of \p nodePtr. So to say, \a partial_1 and
3387 * partial_2 are lifted up to the Q-node \p nodePtr
3388 * and the occurance of their children
3389 * is fixed within the children of \p nodePtr.
3390 */
3391 if (nodePtr->type() != PQNodeRoot::PQNodeType::QNode || nodePtr->partialChildren->size() >= 3) {
3392 return false;
3393 }
3394
3395 bool conssequence = false;
3396 bool found = false;
3397
3398 /*
3399 Check ifthe
3400 pertinent children of [[nodePtr]] form a consecutive sequence. We
3401 differ between two cases:
3402 \begin{enumerate}
3403 \item There exist full children of [[nodePtr]]. First check with
3404 the function [[checkChain]] (\ref{checkChain}) if the full children
3405 form a consecutive sequence. In case that the check was
3406 successful, check if each partial child is adjacent to a full child.
3407 If both checks were successful, the pertient children form a
3408 consecutive sequence.
3409 \item There do not exist full children. Check if the partial
3410 children (there are at most two of them) form a consecutive sequence.
3411 If the test was successful, the pertinent children form a
3412 consecutive sequence.
3413 */
3414 if (!nodePtr->fullChildren->empty()) {
3415 /*
3416 A consecutive
3417 sequence of full children has been detected, containing all full
3418 children of [[nodePtr]]. The chunk checks if each partial child
3419 of [[nodePtr]] is adjacent to a full child. Observe that the
3420 function [[templateQ3]] only reaches this chunk when [[nodePtr]]
3421 has less than three partial children.
3422 */
3423 PQNode<T, X, Y>* fullChild = nodePtr->fullChildren->front();
3424 PQNode<T, X, Y>* fullStart = nullptr;
3425 PQNode<T, X, Y>* fullEnd = nullptr;
3426 conssequence = checkChain(nodePtr, fullChild, &fullStart, &fullEnd);
3427 if (conssequence) {
3429 for (it = nodePtr->partialChildren->begin(); it.valid(); ++it) {
3430 PQNode<T, X, Y>* partial_1 = *it;
3431 found = false;
3432 if ((clientSibLeft(fullStart) == partial_1)
3433 || (clientSibRight(fullStart) == partial_1)
3434 || (clientSibLeft(fullEnd) == partial_1)
3435 || (clientSibRight(fullEnd) == partial_1)) {
3436 found = true;
3437 }
3438 if (!found) {
3439 conssequence = found;
3440 }
3441 }
3442 }
3443 }
3444
3445 else if (nodePtr->partialChildren->size() == 2) {
3446 /*
3447 In case that the node [[nodePtr]] does not have any full children,
3448 this chunk checks if the partial children are adjacent.
3449 */
3450 PQNode<T, X, Y>* partial_1 = nodePtr->partialChildren->front();
3451 PQNode<T, X, Y>* partial_2 = nodePtr->partialChildren->back();
3452 if ((clientSibLeft(partial_1) == partial_2) || (clientSibRight(partial_1) == partial_2)) {
3453 found = true;
3454 }
3455 conssequence = found;
3456 }
3457
3458 if (conssequence) {
3459 removeBlock(nodePtr, true);
3460 }
3461
3462 return conssequence;
3463}
3464
3465}
Declaration and implementation of Array class and Array algorithms.
Declaration and implementation of ArrayBuffer class.
Declaration of doubly linked lists and iterators.
Declaration and implementation of the class PQInternalNode.
Declaration and implementation of the class PQleaf.
Declaration and implementation of the class PQLeafKey.
Declaration and implementation of the class PQNode.
Declaration and implementation of the class PQNodeRoot.
Declaration of singly linked lists and iterators.
Declaration and implementation of list-based queues (classes QueuePure<E> and Queue<E>).
Basic declarations, included by all source files.
An array that keeps track of the number of inserted elements; also usable as an efficient stack.
Definition ArrayBuffer.h:64
E popRet()
Removes the newest element from the buffer and returns it.
void push(E e)
Puts a new element in the buffer.
bool empty() const
Returns true if the buffer is empty, false otherwise.
The parameterized class Array implements dynamic arrays of type E.
Definition Array.h:219
Doubly linked lists (maintaining the length of the list).
Definition List.h:1451
Encapsulates a pointer to a list element.
Definition List.h:113
bool valid() const
Returns true iff the iterator points to an element.
Definition List.h:153
The class template PQInternalNode is used to present P-nodes and Q-nodes in the PQ-Tree.
virtual PQNodeRoot::PQNodeType type() const
Returns the variable m_type in the derived class PQInternalNode.
The datastructure PQ-tree was designed to present a set of permutations on an arbitrary set of elemen...
Definition PQLeaf.h:55
The class template PQLeafKey is a derived class of class template PQBasicKey.
Definition PQLeafKey.h:84
The class template PQBasicKey is an abstract base class.
Definition PQNode.h:56
virtual PQNodeType type() const =0
Returns the variable PQInternalNode::m_type in the derived class PQLeaf and PQInternalNode.
PQNode< T, X, Y > * m_referenceChild
Stores a pointer to one child, the reference child of the doubly linked cirkular list of children of ...
Definition PQNode.h:462
PQNodeType m_parentType
Stores the type of the parent which can be either a P- or Q-node.
Definition PQNode.h:436
bool changeSiblings(PQNode< T, X, Y > *oldSib, PQNode< T, X, Y > *newSib)
The function changeSiblings() replaces the old sibling oldSib of the node by a new sibling newSib.
Definition PQNode.h:539
virtual PQNodeStatus status() const =0
Returns the variable PQLeaf::m_status in the derived class PQLeaf and PQInternalNode.
SibDirection putSibling(PQNode< T, X, Y > *newSib)
The default function putSibling() stores a new sibling at a free sibling pointer of the node.
Definition PQNode.h:252
int m_identificationNumber
Each node that has been introduced once into the tree gets a unique number.
Definition PQNode.h:433
PQNode< T, X, Y > * m_rightEndmost
Stores the right endmost child of a Q-node.
Definition PQNode.h:473
PQNode< T, X, Y > * m_sibLeft
Stores a pointer ot the left sibling of PQNode.
Definition PQNode.h:482
PQNode< T, X, Y > * m_leftEndmost
Definition PQNode.h:447
bool changeEndmost(PQNode< T, X, Y > *oldEnd, PQNode< T, X, Y > *newEnd)
The function changeEndmost() replaces the old endmost child oldEnd of the node by a new child newEnd.
Definition PQNode.h:515
PQNode< T, X, Y > * m_referenceParent
Is a pointer to the parent, in case that the parent is a P-node and the node itself is its reference ...
Definition PQNode.h:470
List< PQNode< T, X, Y > * > * fullChildren
Stores all full children of a node during a reduction.
Definition PQNode.h:498
virtual PQLeafKey< T, X, Y > * getKey() const =0
getKey() returns a pointer to the PQLeafKeyof a node, in case that the node is supposed to have a key...
virtual PQNodeMark mark() const =0
mark() returns the variable PQLeaf::m_mark in the derived class PQLeaf and PQInternalNode.
int m_pertLeafCount
Stores the number of pertinent leaves in the frontier of the node.
Definition PQNode.h:442
PQNode< T, X, Y > * getNextSib(PQNode< T, X, Y > *other) const
The function getNextSib() returns one of the siblings of the node.
Definition PQNode.h:187
PQNode< T, X, Y > * m_parent
Is a pointer to the parent.
Definition PQNode.h:454
List< PQNode< T, X, Y > * > * partialChildren
Stores all partial children of a node during a reduction.
Definition PQNode.h:501
PQNode< T, X, Y > * m_sibRight
Stores a pointer ot the right sibling of PQNode.
Definition PQNode.h:491
int m_pertChildCount
Stores the number of pertinent children of the node.
Definition PQNode.h:439
int m_childCount
Definition PQNode.h:412
bool endmostChild() const
The function endmostChild() checks if a node is endmost child of a Q-node.
Definition PQNode.h:124
PQNode< T, X, Y > * createNodeAndCopyFullChildren(List< PQNode< T, X, Y > * > *fullNodes)
Copies the full children of a P-node that are stored in the stack fullNodes to a new P-node.
Definition PQTree.h:1664
void sortExceptions(int Exceptions[], int arraySize)
Sorts the exceptions before frontExcept() scans the frontier.
Definition PQTree.h:2864
bool checkChain(PQNode< T, X, Y > *nodePtr, PQNode< T, X, Y > *firstFull, PQNode< T, X, Y > **seqStart, PQNode< T, X, Y > **seqEnd)
Checks whether all full children of a Q-node nodePtr form a consecutive sequence.
Definition PQTree.h:1322
virtual bool templateP4(PQNode< T, X, Y > **nodePtr)
Template matching for a P-node with full, empty and exactly one partial children.
Definition PQTree.h:3001
virtual const char * clientPrintType(PQNode< T, X, Y > *nodePtr)
If the user wishes to use different types in a derived class of PQTree that are not available in this...
Definition PQTree.h:1612
virtual const char * clientPrintStatus(PQNode< T, X, Y > *nodePtr)
If the user wishes to use different status in a derived class of PQTree that are not available in thi...
Definition PQTree.h:1607
virtual void destroyNode(PQNode< T, X, Y > *nodePtr)
Marks a node as PQNodeRoot::PQNodeStatus::ToBeDeleted.
Definition PQTree.h:567
virtual bool templateQ1(PQNode< T, X, Y > *nodePtr, bool isRoot)
Template matching for Q-nodes with only full children.
Definition PQTree.h:3242
virtual bool templateP6(PQNode< T, X, Y > **nodePtr)
Template matching for a P-node with full, empty and exactly two partial children.
Definition PQTree.h:3115
virtual bool templateL1(PQNode< T, X, Y > *nodePtr, bool isRoot)
Template matching for leaves.
Definition PQTree.h:2878
virtual PQNode< T, X, Y > * clientRightEndmost(PQNode< T, X, Y > *nodePtr) const
Definition PQTree.h:668
virtual bool templateP1(PQNode< T, X, Y > *nodePtr, bool isRoot)
Template matching for P-nodes with only full children.
Definition PQTree.h:2891
PQNode< T, X, Y > * m_pertinentRoot
a pointer to the root of the pertinent subtree.
Definition PQTree.h:182
List< PQNode< T, X, Y > * > * partialChildren(PQNode< T, X, Y > *nodePtr)
Definition PQTree.h:660
virtual bool Reduce(SListPure< PQLeafKey< T, X, Y > * > &leafKeys)
Performs the reduction of the pertinent leaves with the help of the template matchings,...
Definition PQTree.h:2151
void removeBlock(PQNode< T, X, Y > *nodePtr, bool isRoot)
Of every partial node that is found in the sequence of children of nodePtr, all children are removed ...
Definition PQTree.h:2251
virtual ~PQTree()
Destructor.
Definition PQTree.h:66
virtual bool addNodeToNewParent(PQNode< T, X, Y > *parent, PQNode< T, X, Y > *child, PQNode< T, X, Y > *leftBrother, PQNode< T, X, Y > *rightBrother)
Adds a node child to the children of another node specified in parent.
Definition PQTree.h:877
virtual void Cleanup()
Removes the entire PQ-tree.
Definition PQTree.h:1474
virtual void exchangeNodes(PQNode< T, X, Y > *oldNode, PQNode< T, X, Y > *newNode)
Replaces the oldNode by the newNode in the tree.
Definition PQTree.h:1789
virtual bool templateP5(PQNode< T, X, Y > *nodePtr)
Template matching for a P-node with full, empty children and exactly one partial child.
Definition PQTree.h:3022
void writeGML(const char *fileName)
The function writeGML() prints the PQ-tree in the GML fileformat.
Definition PQTree.h:1969
PQNode< T, X, Y > * m_root
a pointer to the root of the $PQ$-tree.
Definition PQTree.h:179
virtual bool templateQ2(PQNode< T, X, Y > *nodePtr, bool isRoot)
Template matching for Q-nodes with a pertinent sequence of children on one side of the Q-node.
Definition PQTree.h:3261
virtual bool checkIfOnlyChild(PQNode< T, X, Y > *child, PQNode< T, X, Y > *parent)
Checks if child is the only child of parent.
Definition PQTree.h:1454
int m_identificationNumber
Stores the total number of nodes that have been allocated.
Definition PQTree.h:192
void emptyNode(PQNode< T, X, Y > *nodePtr)
Cleans up all stacks, flags and pointers of a pertinent node that has been visited during the reducti...
Definition PQTree.h:1779
virtual bool addNodeToNewParent(PQNode< T, X, Y > *parent, PQNode< T, X, Y > *child)
Adds a node child as a child to another node specified in parent.
Definition PQTree.h:842
virtual PQNode< T, X, Y > * clientNextSib(PQNode< T, X, Y > *nodePtr, PQNode< T, X, Y > *other) const
Definition PQTree.h:672
virtual void emptyAllPertinentNodes()
Cleans up all flags that have been set in the pertinent nodes during the reduction process.
Definition PQTree.h:1744
void writeGML(std::ostream &os)
Definition PQTree.h:1975
virtual int clientPrintNodeCategorie(PQNode< T, X, Y > *nodePtr)
If the user wishes to use different flags in a derived class of PQTree that are not available in this...
Definition PQTree.h:1601
virtual bool templateP3(PQNode< T, X, Y > *nodePtr)
Template matching for a P-node with full and empty children that is not the root of the pertinent sub...
Definition PQTree.h:2935
virtual int removeNodeFromTree(PQNode< T, X, Y > *parent, PQNode< T, X, Y > *child)
The objective is to remove a node child from the PQ-tree.
Definition PQTree.h:2848
int m_numberOfLeaves
Stores the number of leaves.
Definition PQTree.h:195
virtual PQNode< T, X, Y > * clientSibRight(PQNode< T, X, Y > *nodePtr) const
Definition PQTree.h:680
virtual void clientDefinedEmptyNode(PQNode< T, X, Y > *nodePtr)
If the user wishes to use different flags in a derived class of PQTree that are not available in this...
Definition PQTree.h:124
virtual void CleanNode(PQNode< T, X, Y > *)
Definition PQTree.h:103
virtual PQNode< T, X, Y > * clientSibLeft(PQNode< T, X, Y > *nodePtr) const
Definition PQTree.h:676
List< PQNode< T, X, Y > * > * fullChildren(PQNode< T, X, Y > *nodePtr)
Definition PQTree.h:658
virtual void removeChildFromSiblings(PQNode< T, X, Y > *nodePtr)
Removes the node nodePtr from the doubly linked list of its parent.
Definition PQTree.h:2789
List< PQNode< T, X, Y > * > * m_pertinentNodes
Stores all nodes that have been marked PQNodeRoot::PQNodeStatus::Full or PQNodeRoot::PQNodeStatus::Pa...
Definition PQTree.h:205
PQNode< T, X, Y > * m_pseudoRoot
a pointer to the virtual root of the pertinent subtree, in case that the pertinent root cannot be det...
Definition PQTree.h:185
virtual bool Reduction(SListPure< PQLeafKey< T, X, Y > * > &leafKeys)
Tests whether permissible permutations of the elements of U exist such that the elements of a subset ...
Definition PQTree.h:2237
virtual bool templateP2(PQNode< T, X, Y > **nodePtr)
Template matching for a P-node with full and empty children that is the root of the pertinent subtree...
Definition PQTree.h:2906
PQNode< T, X, Y > * root() const
Returns a pointer of the root node of the PQTree.
Definition PQTree.h:169
virtual int Initialize(SListPure< PQLeafKey< T, X, Y > * > &leafKeys)
Initializes the PQ-tree with a set of elements.
Definition PQTree.h:1916
virtual void front(PQNode< T, X, Y > *nodePtr, SListPure< PQLeafKey< T, X, Y > * > &leafKeys)
Returns the keys stored in the leaves of the front of nodePtr.
Definition PQTree.h:1880
bool addNewLeavesToTree(PQInternalNode< T, X, Y > *father, SListPure< PQLeafKey< T, X, Y > * > &leafKeys)
Adds a set of elements to the already existing set of elements of a PQ-tree.
Definition PQTree.h:792
virtual PQNode< T, X, Y > * clientLeftEndmost(PQNode< T, X, Y > *nodePtr) const
Definition PQTree.h:664
virtual bool Bubble(SListPure< PQLeafKey< T, X, Y > * > &leafKeys)
Realizes a function described in [Booth].
Definition PQTree.h:1045
virtual bool templateQ3(PQNode< T, X, Y > *nodePtr)
Definition PQTree.h:3367
virtual void linkChildrenOfQnode(PQNode< T, X, Y > *installed, PQNode< T, X, Y > *newChild)
Links the two endmost children of two different Q-nodes via their sibling pointers together.
Definition PQTree.h:1945
void copyFullChildrenToPartial(PQNode< T, X, Y > *nodePtr, PQNode< T, X, Y > *partialChild)
Copies all full children of nodePtr to a new P-node The node nodePtr has to be a P-node.
Definition PQTree.h:1629
The parameterized class Queue<E> implements list-based queues.
Definition Queue.h:205
int size() const
Returns the number of elements in the queue.
Definition Queue.h:246
E pop()
Removes front element and returns it.
Definition Queue.h:336
bool empty() const
Returns true iff the queue is empty.
Definition Queue.h:243
const_reference top() const
Returns a reference to the front element.
Definition Queue.h:249
iterator append(const E &x)
Adds x at the end of queue.
Definition Queue.h:324
Encapsulates a pointer to an ogdf::SList element.
Definition SList.h:104
bool valid() const
Returns true iff the iterator points to an element.
Definition SList.h:134
Singly linked lists.
Definition SList.h:191
bool empty() const
Returns true iff the list is empty.
Definition SList.h:238
E popFrontRet()
Removes the first element from the list and returns it.
Definition SList.h:544
iterator begin()
Returns an iterator to the first element of the list.
Definition SList.h:344
iterator pushBack(const E &x)
Adds element x at the end of the list.
Definition SList.h:481
#define OGDF_ASSERT(expr)
Assert condition expr. See doc/build.md for more information.
Definition basic.h:52
The namespace for all OGDF objects.