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