Don't import ogdf namespace
[TortoiseGit.git] / ext / OGDF / ogdf / internal / planarity / PQTree.h
blobd271675e230828a563b20901f92ab2d1d7852d60
1 /*
2 * $Revision: 2583 $
4 * last checkin:
5 * $Author: gutwenger $
6 * $Date: 2012-07-12 01:02:21 +0200 (Do, 12. Jul 2012) $
7 ***************************************************************/
9 /** \file
10 * \brief Declaration and implementation of the class PQTree.
12 * \author Sebastian Leipert
14 * \par License:
15 * This file is part of the Open Graph Drawing Framework (OGDF).
17 * \par
18 * Copyright (C)<br>
19 * See README.txt in the root directory of the OGDF installation for details.
21 * \par
22 * This program is free software; you can redistribute it and/or
23 * modify it under the terms of the GNU General Public License
24 * Version 2 or 3 as published by the Free Software Foundation;
25 * see the file LICENSE.txt included in the packaging of this file
26 * for details.
28 * \par
29 * This program is distributed in the hope that it will be useful,
30 * but WITHOUT ANY WARRANTY; without even the implied warranty of
31 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32 * GNU General Public License for more details.
34 * \par
35 * You should have received a copy of the GNU General Public
36 * License along with this program; if not, write to the Free
37 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
38 * Boston, MA 02110-1301, USA.
40 * \see http://www.gnu.org/copyleft/gpl.html
41 ***************************************************************/
44 #ifdef _MSC_VER
45 #pragma once
46 #endif
49 #ifndef OGDF_PQ_TREE_H
50 #define OGDF_PQ_TREE_H
53 #include <string.h>
55 #include <ogdf/basic/Stack.h>
56 #include <ogdf/basic/Queue.h>
57 #include <ogdf/basic/Array.h>
59 #include <ogdf/internal/planarity/PQNode.h>
60 #include <ogdf/internal/planarity/PQInternalNode.h>
61 #include <ogdf/internal/planarity/PQLeaf.h>
62 #include <ogdf/internal/planarity/PQLeafKey.h>
63 #include <ogdf/internal/planarity/PQInternalKey.h>
64 #include <ogdf/internal/planarity/PQNodeKey.h>
67 namespace ogdf {
70 template<class T,class X,class Y>
72 class PQTree
74 public:
76 PQTree();
78 /**
79 * The function shown here is the destructor of the class template PQTree.
80 * In order to free allocated memory, all nodes of the
81 * tree have to be deleted, hence their destructors have to be called.
82 * This is done in the function Cleanup().
83 * Furthermore all other initialized memory has to be freed which is
84 * done as well in the function Cleanup().
86 virtual ~PQTree() { Cleanup(); }
88 bool addNewLeavesToTree(
89 PQInternalNode<T,X,Y> *father,
90 SListPure<PQLeafKey<T,X,Y>*> &leafKeys);
92 void emptyNode(PQNode<T,X,Y>* nodePtr);
94 virtual void front(
95 PQNode<T,X,Y>* nodePtr,
96 SListPure<PQLeafKey<T,X,Y>*> &leafKeys);
98 virtual void CleanNode(PQNode<T,X,Y>* /* nodePtr */) { }
100 virtual void Cleanup();
103 * If the user wishes to use different flags in a derived class of PQTree
104 * that are not available in this implementation, he can overload the function
105 * clientDefinedEmptyNode() in order to make a valid cleanup of the nodes.
106 * It will be called per default by the function emptyAllPertinentNodes().
108 virtual void clientDefinedEmptyNode(PQNode<T,X,Y>* nodePtr) {
109 emptyNode(nodePtr);
112 virtual void emptyAllPertinentNodes();
114 virtual int Initialize(SListPure<PQLeafKey<T,X,Y>*> &leafKeys);
116 virtual bool Reduction(SListPure<PQLeafKey<T,X,Y>*> &leafKeys);
119 * The function root() returns a pointer of the root node of the PQTree.
121 PQNode<T,X,Y>* root() const {
122 return m_root;
125 void writeGML(const char *fileName);
126 void writeGML(ostream &os);
129 protected:
132 //! is a pointer to the root of the $PQ$-tree.
133 PQNode<T,X,Y>* m_root;
135 //! is a pointer to the root of the pertinent subtree.
136 PQNode<T,X,Y>* m_pertinentRoot;
138 //! is a pointer to the virtual root of the pertinent subtree, in case that the pertinent root cannot be detected.
139 PQNode<T,X,Y>* m_pseudoRoot;
141 //! Stores the total number of nodes that have been allocated.
143 * Gives every node that has been used once in the
144 * PQ-tree a unique identification number.
146 int m_identificationNumber;
148 //! Stores the number of leaves.
149 int m_numberOfLeaves;
152 * Stores all nodes that have been marked \b FULL or
153 * \b PARTIAL during a reduction. After the reduction has been
154 * finished succesfully, all pertinent nodes are reinitialized and
155 * prepared for the next reduction. This list also contains pertinent
156 * nodes that have been removed during a reduction. When detected in
157 * the stack, their memory is freed.
159 List<PQNode<T,X,Y>*> *m_pertinentNodes;
162 virtual bool Bubble(SListPure<PQLeafKey<T,X,Y>*> &leafKeys);
164 virtual bool Reduce(SListPure<PQLeafKey<T,X,Y>*> &leafKeys);
166 virtual bool templateL1(PQNode<T,X,Y> *nodePtr, bool isRoot);
168 virtual bool templateP1(PQNode<T,X,Y> *nodePtr, bool isRoot);
170 virtual bool templateP2(PQNode<T,X,Y> **nodePtr);
172 virtual bool templateP3(PQNode<T,X,Y> *nodePtr);
174 virtual bool templateP4(PQNode<T,X,Y> **nodePtr);
176 virtual bool templateP5(PQNode<T,X,Y> *nodePtr);
178 virtual bool templateP6(PQNode<T,X,Y> **nodePtr);
180 virtual bool templateQ1(PQNode<T,X,Y> *nodePtr, bool isRoot);
182 virtual bool templateQ2(PQNode<T,X,Y> *nodePtr, bool isRoot);
184 virtual bool templateQ3(PQNode<T,X,Y> *nodePtr);
188 virtual bool addNodeToNewParent(
189 PQNode<T,X,Y>* parent,
190 PQNode<T,X,Y>* child);
192 virtual bool addNodeToNewParent(
193 PQNode<T,X,Y>* parent,
194 PQNode<T,X,Y>* child,
195 PQNode<T,X,Y>* leftBrother,
196 PQNode<T,X,Y>* rightBrother);
198 virtual bool checkIfOnlyChild(
199 PQNode<T,X,Y> *child,
200 PQNode<T,X,Y> *parent);
203 * The function destroyNode() marks a node as TO_BE_DELETED. This
204 * enables the function emptyAllPertinentNodes()
205 * to remove the node and free its memory.
207 virtual void destroyNode(PQNode<T,X,Y> *nodePtr) {
208 nodePtr->status(PQNodeRoot::TO_BE_DELETED);
211 virtual void exchangeNodes(
212 PQNode<T,X,Y> *oldNode,
213 PQNode<T,X,Y> *newNode);
215 virtual void linkChildrenOfQnode(
216 PQNode<T,X,Y> *installed,
217 PQNode<T,X,Y> *newChild);
219 virtual void removeChildFromSiblings(PQNode<T,X,Y>* nodePtr);
221 virtual int removeNodeFromTree(
222 PQNode<T,X,Y>* parent,
223 PQNode<T,X,Y>* child);
226 List<PQNode<T,X,Y>*>* fullChildren(PQNode<T,X,Y>* nodePtr) {
227 return nodePtr->fullChildren;
231 List<PQNode<T,X,Y>*>* partialChildren(PQNode<T,X,Y>* nodePtr) {
232 return nodePtr->partialChildren;
235 virtual PQNode<T,X,Y>* clientLeftEndmost(PQNode<T,X,Y>* nodePtr) const {
236 return nodePtr->m_leftEndmost;
239 virtual PQNode<T,X,Y>* clientRightEndmost(PQNode<T,X,Y>* nodePtr) const {
240 return nodePtr->m_rightEndmost;
243 virtual PQNode<T,X,Y>* clientNextSib(PQNode<T,X,Y>* nodePtr,
244 PQNode<T,X,Y>* other) const {
245 return nodePtr->getNextSib(other);
248 virtual PQNode<T,X,Y>* clientSibLeft(PQNode<T,X,Y>* nodePtr) const {
249 return nodePtr->m_sibLeft;
252 virtual PQNode<T,X,Y>* clientSibRight(PQNode<T,X,Y>* nodePtr) const {
253 return nodePtr->m_sibRight;
256 virtual int clientPrintNodeCategorie(PQNode<T,X,Y>* nodePtr);
258 virtual const char* clientPrintStatus(PQNode<T,X,Y>* nodePtr);
260 virtual const char* clientPrintType(PQNode<T,X,Y>* nodePtr);
262 private:
264 bool checkChain(
265 PQNode<T,X,Y> *nodePtr,
266 PQNode<T,X,Y> *firstFull,
267 PQNode<T,X,Y> **seqStart,
268 PQNode<T,X,Y> **seqEnd);
270 void copyFullChildrenToPartial(
271 PQNode<T,X,Y> *nodePtr,
272 PQNode<T,X,Y> *partialChild);
274 PQNode<T,X,Y>* createNodeAndCopyFullChildren(List<PQNode<T,X,Y>*> *fullNodes);
276 void printNode(
277 char *filename,
278 int number,
279 PQNode<T,X,Y>* father,
280 PQNode<T,X,Y>* son);
282 void removeBlock(PQNode<T,X,Y> *nodePtr, bool isRoot);
284 void sortExceptions(int Exceptions[], int arraySize);
289 /************************************************************************
290 addNewLeavesToTree
291 ************************************************************************/
294 * The function addNewLeavesToTree() adds a set of elements to the already
295 * existing set of elements of a PQ-tree.
296 * These elements have to be of type PQLeafKey
297 * and are handed to the function in an array leafKeys.
298 * The father of the new elements that has to be an existing P- or Q-node,
299 * has to be specified and is not allowed to have children.
301 * The above mentioned facts
302 * are checked by the function addNodeToNewParent() and the process
303 * of adding a child to parent is interrupted with an error message
304 * returning 0 as soon none of the facts is fullfilled.
305 * The function addNewLeavesToTree() returns 1 if it
306 * succeeded in adding the leaves to parent.
309 template<class T,class X,class Y>
310 bool PQTree<T,X,Y>::addNewLeavesToTree(
311 PQInternalNode<T,X,Y> *father,
312 SListPure<PQLeafKey<T,X,Y>*> &leafKeys)
314 if (!leafKeys.empty())
316 OGDF_ASSERT(!father->m_childCount)
317 // Father has children. Brothers expected
319 /// Enter the first element as PQLeaf to the [[parent]].
320 SListIterator<PQLeafKey<T,X,Y>*> it = leafKeys.begin();
321 PQLeafKey<T,X,Y>* newKey = *it; //leafKeys[0];
323 PQNode<T,X,Y>* aktualSon = OGDF_NEW PQLeaf<T,X,Y>(m_identificationNumber++,PQNodeRoot::EMPTY,newKey);
324 PQNode<T,X,Y>* firstSon = aktualSon;
325 firstSon->m_parent = father;
326 firstSon->m_parentType = father->type();
327 father->m_childCount++;
328 PQNode<T,X,Y>* oldSon = firstSon;
330 /// Enter all other elements as leaves to [[parent]].
331 for (++it; it.valid(); ++it)
333 newKey = *it; //leafKeys[i];
334 aktualSon = OGDF_NEW PQLeaf<T,X,Y>(m_identificationNumber++,
335 PQNodeRoot::EMPTY,newKey);
336 aktualSon->m_parent = father;
337 aktualSon->m_parentType = father->type();
338 father->m_childCount++;
339 oldSon->m_sibRight = aktualSon;
340 aktualSon->m_sibLeft = oldSon;
341 oldSon = aktualSon;
343 if (father->type() == PQNodeRoot::PNode)
344 /// Set the reference pointers if [[parent]] is a $P$-node.
346 firstSon->m_sibLeft = oldSon;
347 oldSon->m_sibRight = firstSon;
348 father->m_referenceChild = firstSon;
349 firstSon->m_referenceParent = father;
351 else if (father->type() == PQNodeRoot::QNode)
352 /// Set the endmost children if [[parent is a $Q$-node.
354 father->m_leftEndmost = firstSon;
355 father->m_rightEndmost = oldSon;
357 return true;
360 return false;
365 /************************************************************************
366 addNodeToNewParent
367 ************************************************************************/
370 * The function addNodeToNewParent() adds a node \a child as a child
371 * to another node specified in \a parent.
372 * The \a parent of the new node has to be an existing P- or Q-node and
373 * is \b not allowed to have children.
374 * In the case, that \a parent has children, addNewNodeToParent()
375 * returns 0 printing an error-message.
376 * In this case, use the function addNodeToParent() while specifying the future
377 * siblings of \a child. See addNodeToNewParent2() for more
378 * details.
380 * After successfully inserting \a child to \a parent the function
381 * addNewNodeToParent() returns 1. Otherwise it returns
382 * 0.
385 template<class T,class X,class Y>
386 bool PQTree<T,X,Y>::addNodeToNewParent(
387 PQNode<T,X,Y>* parent,
388 PQNode<T,X,Y>* child)
390 OGDF_ASSERT(parent->type() == PQNodeRoot::PNode && parent->type() == PQNodeRoot::QNode)
391 //parent type not valid.
393 if (child != 0)
395 OGDF_ASSERT(parent->m_childCount == 0)
396 //when adding new nodes: Brothers expected.
397 child->m_parent = parent;
398 child->m_parentType = parent->type();
399 parent->m_childCount++;
402 Set the reference pointers in case that [[parent]] is a $P$-node.
403 If [[parent]] is a $Q$-node, this chunk sets the endmost children
404 of [[parent]]. Since [[child]] is the only child of [[parent]]
405 both endmost pointers are set to [[child]].
407 if (parent->type() == PQNodeRoot::PNode)
409 child->m_sibLeft = child;
410 child->m_sibRight = child;
411 parent->m_referenceChild = child;
412 child->m_referenceParent = parent;
414 else if (parent->type() == PQNodeRoot::QNode)
416 parent->m_leftEndmost = child;
417 parent->m_rightEndmost = child;
420 return true;
423 return false;
427 /************************************************************************
428 addNodeToNewParent
429 ************************************************************************/
432 * The function addNodeToNewParent() adds a node \a child to the children
433 * of another node specified in \a parent.
434 * The \a parent of the new node has to be an existing P- or Q-node and
435 * is allowed to have children. In case that \a parent has children,
436 * the siblings of the new introduced child <b> must be specified</b>.
437 * If no siblings are specified, the function addNodeToNewParent(PQNode<T,X,Y>*,PQNode<T,X,Y>*)
438 * is called by default.
439 * If the \a parent is not specified, the function assumes that
440 * \a child is added as interior child to a Q-node.
442 * The client of this function should observe the following facts:
443 * - If \a parent is a P-node, than only one sibling is needed in order
444 * to enter the \a child. If the client specifies two siblings in \a leftBrother
445 * and \a rightBrother, then an arbitrary one is choosen to be a sibling.
446 * - If \a parent is a Q-node, two siblings <b>must be specified</b> if
447 * \a child has to become an interior child of the Q-node. If just
448 * one sibling is specified, this implies that \a child is about to become
449 * a new endmost child of \a parent. So either \a leftBrother or
450 * \a rightBrother must store an existing endmost child of \a parent.
451 * - If \a parent is a zero pointer, addNodeToNewParents() assumes
452 * that \a child is added as interior child to a Q-node. In this
453 * case \b both siblings of \a child <b>have to be specified</b>. Observe
454 * however, that it is also legal to specify the parent in this case.
456 * The above mentioned facts
457 * are checked by the function addNodeToNewParent() and the process
458 * of adding a child to \a parent is interrupted with an error message
459 * returning 0 as soon
460 * none of the facts is fullfilled.
461 * The function addNodeToNewParent() returns 1 if it
462 * succeeded in adding the \a child to \a parent.
465 template<class T,class X,class Y>
466 bool PQTree<T,X,Y>::addNodeToNewParent(
467 PQNode<T,X,Y>* parent,
468 PQNode<T,X,Y>* child,
469 PQNode<T,X,Y>* leftBrother,
470 PQNode<T,X,Y>* rightBrother)
473 if (parent != 0)
475 OGDF_ASSERT(parent->type() == PQNodeRoot::PNode || parent->type() == PQNodeRoot::QNode)
476 //parent type not valid
477 if ((leftBrother == 0) && (rightBrother == 0))
478 return addNodeToNewParent(parent,child);
479 else if (child != 0)
481 child->m_parent = parent;
482 child->m_parentType = parent->type();
483 parent->m_childCount++;
485 if (parent->type() == PQNodeRoot::PNode)
488 The parent is a $P$-node with children.
489 Either [[leftBrother]] or [[rightBrother]] stores
490 a pointer to an existing child of [[parent]] and [[parent]]
491 is a $P$-node. In case that two brothers are stored, an
492 arbitrary one is choosen to be the next sibling of [[child]].
493 This brother is stored in [[brother]]. The pointer [[sister]]
494 denotes a pointer to an arbitrary sibling of [[brother]].
496 PQNode<T,X,Y>* brother = (leftBrother != 0) ? leftBrother : rightBrother;
497 PQNode<T,X,Y>* sister = brother->m_sibRight;
498 child->m_sibLeft = brother;
499 child->m_sibRight = sister;
500 brother->m_sibRight = child;
501 sister->m_sibLeft = child;
502 return true;
505 else if (leftBrother == 0)
508 The parent is a $Q$-node with children.
509 The [[leftBrother]] is a [[0]]-pointer while the
510 [[rightBrother]] denotes an existing child of [[parent]].
511 The node [[rightBrother]] {\bf must be} one of the two endmost
512 children of [[parent]]. If this is not the case, the chunk
513 detects this, halts the procedure [[addNewLeavesToTree]]
514 printing an error message and returning [[0]].
515 If [[rightBrother]] is endmost child of [[parent]], then
516 this chunk adds [[child]] at the one end where
517 [[rightBrother]] hides. The node [[child]] is then made the
518 new endmost child of [[parent]] on the corresponding side.
520 if (rightBrother == parent->m_leftEndmost)
522 parent->m_leftEndmost = child;
523 child->m_sibRight = rightBrother;
524 rightBrother->putSibling(child,PQNodeRoot::LEFT);
525 return true;
528 // missing second brother?
529 OGDF_ASSERT(rightBrother == parent->m_rightEndmost);
530 parent->m_rightEndmost = child;
531 child->m_sibLeft = rightBrother;
532 rightBrother->putSibling(child,PQNodeRoot::LEFT);
533 return true;
536 else if (rightBrother == 0)
539 The parent is a $Q$-node with children.
540 The [[rightBrother]] is a [[0]]-pointer while the
541 [[leftBrother]] denotes an existing child of [[parent]]. The
542 node [[leftBrother]] {\bf must be} one of the two endmost
543 children of [[parent]]. If this is not the case, the chunk
544 detects this, halts the procedure [[addNodeToNewParent]]
545 printing an error message and returning [[0]].
546 If [[leftBrother]] is endmost child of [[parent]], then this
547 chunk adds [[child]] at the one end where [[leftBrother]]
548 hides. The node [[child]] is then made new endmost child of
549 [[parent]] on the corresponding side.
551 if (leftBrother == parent->m_rightEndmost)
553 parent->m_rightEndmost = child;
554 child->m_sibLeft = leftBrother;
555 leftBrother->putSibling(child,PQNodeRoot::RIGHT);
556 return true;
559 // missing second brother?
560 OGDF_ASSERT(leftBrother == parent->m_leftEndmost);
561 parent->m_leftEndmost = child;
562 child->m_sibRight = leftBrother;
563 leftBrother->putSibling(child,PQNodeRoot::RIGHT);
564 return true;
567 else
570 The parent is a $Q$-node with children.
571 Both the [[rightBrother]] and the [[leftBrother]] denote
572 existing children of [[parent]]. In this case, [[leftBrother]]
573 and [[rightBrother]] must be immideate siblings. If this is
574 not the case, this will be detected during the function call
575 [[changeSiblings]] of the class [[PQNode.h]] (see
576 \ref{PQNode.changeSiblings}) in the first two lines of this
577 chunk. If the chunk recognizes the failure of
578 [[changeSiblings]] it halts the procedure
579 [[addNewLeavesToTree]], printing an error message and
580 returning [[0]].
581 If the two brothers are immediate siblings, this chunk
582 adds [[child]] between the two brothers as interior child of
583 the $Q$-node [[parent]].
585 #ifdef OGDF_DEBUG
586 bool ok =
587 #endif
588 rightBrother->changeSiblings(leftBrother,child) && leftBrother->changeSiblings(rightBrother,child);
590 // brothers are not siblings?
591 OGDF_ASSERT(ok);
593 if (leftBrother->m_sibRight == child)
595 child->m_sibLeft = leftBrother;
596 child->m_sibRight = rightBrother;
598 else
600 child->m_sibLeft = rightBrother;
601 child->m_sibRight = leftBrother;
603 return true;
606 else
607 return false;
609 else if (leftBrother != 0 && rightBrother != 0)
612 The parent is a $Q$-node with children.
613 Both the [[rightBrother]] and the [[leftBrother]] denote
614 existing children of [[parent]]. In this case, [[leftBrother]]
615 and [[rightBrother]] must be immideate siblings. If this is
616 not the case, this will be detected during the function call
617 [[changeSiblings]] of the class [[PQNode.h]] (see
618 \ref{PQNode.changeSiblings}) in the first two lines of this
619 chunk. If the chunk recognizes the failure of
620 [[changeSiblings]] it halts the procedure
621 [[addNewLeavesToTree]], printing an error message and
622 returning [[0]].
623 If the two brothers are immediate siblings, this chunk
624 adds [[child]] between the two brothers as interior child of
625 the $Q$-node [[parent]].
627 #ifdef OGDF_DEBUG
628 bool ok =
629 #endif
630 rightBrother->changeSiblings(leftBrother,child) && leftBrother->changeSiblings(rightBrother,child);
632 // brothers are not siblings?
633 OGDF_ASSERT(ok);
635 if (leftBrother->m_sibRight == child)
637 child->m_sibLeft = leftBrother;
638 child->m_sibRight = rightBrother;
640 else
642 child->m_sibLeft = rightBrother;
643 child->m_sibRight = leftBrother;
645 return true;
648 return true;
653 /************************************************************************
654 Bubble
655 ************************************************************************/
658 * The function Bubble() realizes a function described in [Booth].
659 * It <em>bubbles</em> up from the pertinent leaves to the pertinent root
660 * in order to make sure that every pertinent node in the pertinent subtree
661 * has a valid pointer to its parent. If Bubble() does not succed in doing so,
662 * then the set of elements, stored in the \a leafKeys cannot form
663 * a consecutive sequence.
665 * The function Bubble() uses a wide variaty of variables, explained
666 * in detail below.
667 * - \a blockcount is the number of blocks of blocked nodes during
668 * the bubbling up phase.
669 * - \a numBlocked is the number of blocked nodes during the
670 * bubbling up phase.
671 * - \a blockedSiblings counts the number of blocked siblings that
672 * are adjacent to \a checkNode. A node has 0, 1 or 2 blocked siblings.
673 * A child of a P-node has no blocked siblings. Endmost children of
674 * Q-nodes have at most 1 blocked sibling. The interior children of
675 * a Q-Node have at most 2 blocked siblings.
676 * - \a checkLeaf is a pointer used for finding the pertinent leaves.
677 * - \a checkNode is a pointer to the actual node.
678 * - \a checkSib is a pointer used to examin the siblings of [[checkNode]].
679 * - \a offTheTop is a variable which is either 0 (that is its
680 * initial value) or 1 in case that the root of the tree has been
681 * process during the first phase.
682 * - \a parent is a pointer to the parent of \a checkNode, if \a checkNode
683 * has a valid parent pointer.
684 * - \a processNodes is a first-in first-out list that is used for
685 * sequencing the order in which the nodes are processed.
686 * - \a blockedNodes is a stack storing all nodes that have been
687 * once blocked. In case that the [[m_pseudoRoot]] has to be
688 * introduced, the stack contains the blocked nodes.
691 template<class T,class X,class Y>
692 bool PQTree<T,X,Y>::Bubble(SListPure<PQLeafKey<T,X,Y>*> &leafKeys)
694 Queue<PQNode<T,X,Y>*> processNodes;
697 Enter the [[Full]] leaves into the queue [[processNodes]].
698 In a first step the pertinent leaves have to be identified in the tree
699 and entered on to the queue [[processNodes]]. The identification of
700 the leaves can be done with the help of a pointer stored in every
701 [[PQLeafKey]] (see \ref{PQLeafKey}) in constant time for every element.
703 SListIterator<PQLeafKey<T,X,Y>*> it;
704 for (it = leafKeys.begin(); it.valid(); ++it)
706 PQNode<T,X,Y>* checkLeaf = (*it)->nodePointer(); //leafKeys[i]->nodePointer();
707 checkLeaf->mark(PQNodeRoot::QUEUED);
708 processNodes.append(checkLeaf);
709 m_pertinentNodes->pushFront(checkLeaf);
712 int blockCount = 0;
713 int numBlocked = 0;
714 int offTheTop = 0;
715 int blockedSiblings = 0;
716 PQNode<T,X,Y>* checkSib = 0;
717 Stack<PQNode<T,X,Y>*> blockedNodes;
719 while ((processNodes.size() + blockCount + offTheTop) > 1)
721 if (processNodes.size() == 0)
723 No consecutive sequence possible.
724 The queue [[processNodes]] does not contain any nodes for
725 processing and the sum of [[blockCount]] and [[offTheTop]] is
726 greater than 1. If the queue is empty, the root of the pertinent
727 subtree was already processed. Nevertheless, there are blocked
728 nodes since [[offTheTop]] is either be [[0]] or [[1]], hence
729 [[blockCount]] must be at least [[1]]. Such blocked nodes cannot
730 form a consecutive sequence with all nodes in the set
731 [[leafKeys]]. Observe that this chunk finishes the function
732 [[Bubble]]. Hence every memory allocated by the function [[Bubble]]
733 has to be deleted here as well.
735 return false;
737 If there are still nodes to be processed in which case the queue
738 [[processNodes]] is not empty, we get the next node from the queue.
739 By default this node has to be marked as blocked.
741 PQNode<T,X,Y>* checkNode = processNodes.pop();
742 blockedNodes.push(checkNode);
743 checkNode->mark(PQNodeRoot::BLOCKED);
744 blockedSiblings = 0;
747 Check if node is adjacent to an unblocked node.
748 After getting the node [[checkNode]] from the queue, its siblings are
749 checked, whether they are unblocked. If they are, then they have a
750 valid pointer to their parent and the parent pointer of [[checkNode]]
751 is updated.
753 if ((checkNode->m_parentType != PQNodeRoot::PNode) && (checkNode != m_root))
754 // checkNode is son of a QNode.
755 // Check if it is blocked.
757 if (clientSibLeft(checkNode) == 0)
758 // checkNode is endmost child of
759 // a QNode. It has a valid pointer
760 // to its parent.
762 checkNode->mark(PQNodeRoot::UNBLOCKED);
763 if (clientSibRight(checkNode) &&
764 clientSibRight(checkNode)->mark() == PQNodeRoot::BLOCKED)
765 blockedSiblings++;
768 else if (clientSibRight(checkNode) == 0)
769 // checkNode is endmost child of
770 // a QNode. It has a valid pointer
771 // to its parent.
773 checkNode->mark(PQNodeRoot::UNBLOCKED);
774 if (clientSibLeft(checkNode) &&
775 clientSibLeft(checkNode)->mark() == PQNodeRoot::BLOCKED)
776 blockedSiblings++;
780 else
781 // checkNode is not endmost child of
782 // a QNode. It has not a valid
783 // pointer to its parent.
785 if (clientSibLeft(checkNode)->mark() == PQNodeRoot::UNBLOCKED)
786 // checkNode is adjacent to an
787 // unblocked node. Take its parent.
789 checkNode->mark(PQNodeRoot::UNBLOCKED);
790 checkNode->m_parent = clientSibLeft(checkNode)->m_parent;
792 else if (clientSibLeft(checkNode)->mark() == PQNodeRoot::BLOCKED)
793 blockedSiblings++;
795 if (clientSibRight(checkNode)->mark() == PQNodeRoot::UNBLOCKED)
796 // checkNode is adjacent to an
797 // unblocked node. Take its parent.
799 checkNode->mark(PQNodeRoot::UNBLOCKED);
800 checkNode->m_parent = clientSibRight(checkNode)->m_parent;
802 else if (clientSibRight(checkNode)->mark() == PQNodeRoot::BLOCKED)
803 blockedSiblings++;
807 else
808 // checkNode is son of a PNode
809 // and children of P_NODEs
810 // cannot be blocked.
811 checkNode->mark(PQNodeRoot::UNBLOCKED);
813 if (checkNode->mark() == PQNodeRoot::UNBLOCKED)
815 PQNode<T,X,Y>* parent = checkNode->m_parent;
818 Get maximal consecutive set of blocked siblings.
819 This chunk belongs to the procedure [[bubble]].
820 The node [[checkNode]] is [[UNBLOCKED]].
821 If the parent of [[checkNode]] is a $Q$-Node, then we check the
822 siblings [[checkSib]] of [[checkNode]] whether they are
823 [[BLOCKED]]. If they are blocked, they have to be marked
824 [[UNBLOCKED]] since they are adjacent to the [[UNBLOCKED]] node
825 [[checkNode]]. We then have to proceed with the siblings of
826 [[checkSib]] in order to find [[BLOCKED]] nodes
827 adjacent to [[checkSib]]. This is repeated until no [[BLOCKED]]
828 nodes are found any more.
830 Observe that while running through the children of the $Q$-Node
831 (referred by the pointer [[parent]]), their parent pointers,
832 as well as the [[pertChildCount]] of [[parent]] are updated.
833 Furthermore we reduce simultaneously the count [[numBlocked]].
835 if (blockedSiblings > 0)
837 if (clientSibLeft(checkNode) != 0)
839 checkSib = clientSibLeft(checkNode);
840 PQNode<T,X,Y>* oldSib = checkNode;
841 while (checkSib->mark() == PQNodeRoot::BLOCKED)
843 checkSib->mark(PQNodeRoot::UNBLOCKED);
844 checkSib->m_parent = parent;
845 numBlocked--;
846 parent->m_pertChildCount++;
847 PQNode<T,X,Y>* holdSib = clientNextSib(checkSib,oldSib);
848 oldSib = checkSib;
849 checkSib = holdSib;
850 //Blocked node as endmost child of a QNode.
854 if (clientSibRight(checkNode) != 0)
856 checkSib = clientSibRight(checkNode);
857 PQNode<T,X,Y>* oldSib = checkNode;
858 while (checkSib->mark() == PQNodeRoot::BLOCKED)
860 checkSib->mark(PQNodeRoot::UNBLOCKED);
861 checkSib->m_parent = parent;
862 numBlocked--;
863 parent->m_pertChildCount++;
864 PQNode<T,X,Y>* holdSib = clientNextSib(checkSib,oldSib);
865 oldSib = checkSib;
866 checkSib = holdSib;
867 //Blocked node as endmost child of a QNode.
870 }// if (blockedSiblings > 0)
874 Process parent of [[checkNode]]
875 After processing the siblings of the [[UNBLOCKED]] [[checkNode]]
876 the parent has to be processed. If [[checkNode]] is the root
877 of the tree we do nothing except setting the flag [[offTheTop]].
878 If it is not the root and [[parent]] has not been placed onto the
879 queue [[processNodes]], the [[parent]] is placed on to
880 [[processNodes]].
882 Observe that the number [[blockCount]] is updated. Since
883 [[checkNode]] was [[UNBLOCKED]] all perinent nodes adjacent
884 to that node became [[UNBLOCKED]] as well. Therefore the number
885 of blocks is reduced by the number of [[BLOCKED]] siblings of
886 [[checkNode]].
888 if (parent == 0)
889 // checkNode is root of the tree.
890 offTheTop = 1;
891 else
892 // checkNode is not the root.
894 parent->m_pertChildCount++;
895 if (parent->mark() == PQNodeRoot::UNMARKED)
897 processNodes.append(parent);
898 m_pertinentNodes->pushFront(parent);
899 parent->mark(PQNodeRoot::QUEUED);
903 blockCount -= blockedSiblings;
904 blockedSiblings = 0;
906 }//if (checkNode->mark() == UNBLOCKED)
908 else
911 Process blocked [[checkNode]]
912 Since [[checkNode]] is [[BLOCKED]], we cannot continue
913 processing at this point in the Tree. We have to wait until
914 this node becomes unblocked. So only the variables
915 [[blockCount]] and [[numBlocked]] are updated.
917 blockCount += 1 - blockedSiblings;
918 numBlocked++;
921 }//while ((processNodes.size() + blockCount + offTheTop) > 1)
923 if (blockCount == 1)
926 If [[blockCount]] $= 1$ enter [[m_pseudoRoot]] to the tree
927 In case that the root of the pertinent subtree is a $Q$-node
928 with empty children on both sides and the pertinent children
929 in the middle, it is possible that the $PQ$-tree is reducible.
930 But since the sequence of pertinent children of the $Q$-node is
931 blocked, the procedure is not able to find the parent of its
932 pertinent children. This is due to the fact that the interior
933 children of a $Q$-node do not have a valid parent pointer.
935 So the root of the pertinent subtree is not known, hence cannot be
936 entered into the processing queue used in the function call [[Reduce]]
937 (see \ref{Reduce}). To solve this problem a special node only designed
938 for this cases is used: [[m_pseudoRoot]]. It simulates the root of the
939 pertinent subtree. This works out well, since for this node the only
940 possible template maching is [[templateQ3]] (see \ref{templateQ3}),
941 where no pointers to the endmost children of a $Q$-node are used.
943 while (!blockedNodes.empty())
945 PQNode<T,X,Y>* checkNode = blockedNodes.pop();
946 if (checkNode->mark() == PQNodeRoot::BLOCKED)
948 checkNode->mark(PQNodeRoot::UNBLOCKED);
949 checkNode->m_parent = m_pseudoRoot;
950 m_pseudoRoot->m_pertChildCount++;
951 OGDF_ASSERT(!checkNode->endmostChild())
952 //Blocked node as endmost child of a QNode.
957 return true;
961 /************************************************************************
962 checkChain
963 ************************************************************************/
966 * The function checkChain() is used by the function templateQ2()
967 * and templateQ3().
968 * It checks whether all full children of a Q-node
969 * \a nodePtr form a consecutive sequence. If the full nodes do so,
970 * the procedure returns 1 as a result, otherwise 0.
972 * The pointer \a firstFull denotes just an arbirtary full child. Starting
973 * from this position, checkChain sweeps through the consecutive
974 * sequence, halting as soon as a nonfull child is detected.
975 * The two pointers \a seqStart and \a seqEnd are set within the
976 * function \a checkChain. They denote the first and last node of the consecutive
977 * sequence.
979 * The client should observe that it is not possible to avoid the use
980 * of such a function. According to the procedure Bubble() children of
981 * Q-nodes get unblocked as soon as they are adjacent to any pertinent
982 * sibling. This includes that chains of more than two partial children
983 * are regarded as unblocked as well.
984 * Such chains are of course not reducible and therefore
985 * have to be detected by the function checkChain().
987 * Following we give an overview of the variables used in
988 * checkChain().
989 * - \a fullCount counts the number of children that are
990 * discovered by the function checkChain(). This is necessary, since
991 * checkChain() is used by two template matching functions
992 * templateQ2() and templateQ3() where in the latter case the
993 * pointer \a firstFull may point to any full child in the front of the Q-node
994 * \a nodePtr.
995 * - \a notFull is set 1 when an empty child is encountered.
996 * - \a checkNode is the actual node that is examined.
997 * - \a leftNext is the next node that has to be examined on the
998 * left side of \a firstFull.
999 * - \a leftOld is the node that has been examined right before
1000 * \a checkNode on the left side of \a firstFull.
1001 * - \a rightNext is the next node that has to be examined on the
1002 * right side of \a firstFull. Not needed when checkChain() was
1003 * called by templateQ2().
1004 * - \a rightOld is the node that has been examined right before
1005 * \a checkNode on the right side of \a firstFull.
1006 * Not needed when checkChain() was called by templateQ2().
1009 template<class T,class X,class Y>
1010 bool PQTree<T,X,Y>::checkChain(
1011 PQNode<T,X,Y> *nodePtr,
1012 PQNode<T,X,Y> *firstFull,
1013 PQNode<T,X,Y> **seqStart,
1014 PQNode<T,X,Y> **seqEnd)
1016 bool notFull = false;
1017 int fullCount = nodePtr->fullChildren->size();
1018 fullCount--; // firstFull does have a FULL label.
1021 Start at the [[firstFull]] child sweeping through the full children on
1022 the left side of [[firstfull]]. It stops as soon as a nonfull child is
1023 detected. The last found full child is stored in [[seqEnd]].
1025 PQNode<T,X,Y> *leftNext = clientSibLeft(firstFull);
1026 (*seqEnd) = firstFull;
1027 if (leftNext != 0)
1029 if (leftNext->status() == PQNodeRoot::FULL) {
1030 fullCount--;
1032 PQNode<T,X,Y> *leftOld = firstFull;
1033 PQNode<T,X,Y> *checkNode = leftNext;
1035 while (fullCount > 0 && !notFull)
1036 // There are still full children to be
1037 // counted, and no empty child has been
1038 // encountered on this side.
1040 leftNext = clientNextSib(checkNode,leftOld);
1041 if (leftNext != 0 && leftNext->status() == PQNodeRoot::FULL)
1042 fullCount--;
1043 else
1044 notFull = true;
1045 leftOld = checkNode;
1046 checkNode = leftNext;
1049 if (checkNode != 0 && checkNode->status() == PQNodeRoot::FULL)
1050 (*seqEnd) = checkNode;
1052 else {
1053 //searching consecutive sequence in Q2 or Q3.
1054 OGDF_ASSERT(leftOld != 0 && leftOld->status() == PQNodeRoot::FULL);
1055 (*seqEnd) = leftOld;
1058 } else {
1059 (*seqEnd) = firstFull;
1064 Start at the [[firstFull]] child sweeping through the full children on
1065 the right side of [[firstfull]]. It stops as soon as a nonfull child is
1066 detected.
1068 notFull = false;
1069 PQNode<T,X,Y> *rightNext = clientSibRight(firstFull);
1070 (*seqStart) = firstFull;
1071 if(rightNext != 0)
1073 if (rightNext->status() == PQNodeRoot::FULL) {
1074 fullCount--;
1076 PQNode<T,X,Y> *rightOld = firstFull;
1077 PQNode<T,X,Y> *checkNode = rightNext;
1079 while (fullCount > 0 && !notFull)
1080 // There are still full children to be
1081 // counted, and no empty child has been
1082 // encountered on this side.
1084 rightNext = clientNextSib(checkNode,rightOld);
1085 if (rightNext != 0 && rightNext->status() == PQNodeRoot::FULL)
1086 fullCount--;
1087 else
1088 notFull = true;
1089 rightOld = checkNode;
1090 checkNode = rightNext;
1092 if (checkNode != 0 && checkNode->status() == PQNodeRoot::FULL)
1093 (*seqStart) = checkNode;
1095 else {
1096 OGDF_ASSERT(rightOld != 0 && rightOld->status() == PQNodeRoot::FULL);
1097 (*seqStart) = rightOld;
1098 //searching consecutive seqeuence in Q2 or Q3.
1101 } else {
1102 (*seqStart) = firstFull;
1108 if (firstFull == (*seqEnd))
1110 PQNode<T,X,Y> *checkNode = (*seqEnd);
1111 (*seqEnd) = (*seqStart);
1112 (*seqStart) = checkNode;
1115 if (fullCount == 0)
1116 // All full children occupy a consecutive
1117 // sequence.
1118 return true;
1119 else
1120 return false;
1124 /************************************************************************
1125 checkIfOnlyChild
1126 ************************************************************************/
1129 * The function checkIfOnlyChild() checks if \a child is the only
1130 * child of \a parent. If so, \a child is connected to its
1131 * grandparent, as long as parent is not the root of the tree. In case
1132 * that \a parent is the root of the tree and \a child is its only
1133 * child, the node \a child becomes the new root of the tree. The parent then
1134 * is completely removed from the tree and destroyd. The return value of
1135 * the method checkIfOnlyChild() is 1, if \a child was the only
1136 * child of parent. Otherwise the return value is 0.
1137 * Before applying the function exchangeNodes(), the function removeChildFromSiblings()
1138 * is applied. This is usefull in case
1139 * the node \a parent has some ignored children and has to be reused
1140 * within some extra algorithmic context.
1143 template<class T,class X,class Y>
1144 bool PQTree<T,X,Y>::checkIfOnlyChild(
1145 PQNode<T,X,Y> *child,
1146 PQNode<T,X,Y> *parent)
1149 if ((parent->type() == PQNodeRoot::PNode && parent->m_childCount == 1)
1150 || (parent->type() == PQNodeRoot::QNode && parent->m_leftEndmost == child
1151 && parent->m_rightEndmost == child))
1153 removeChildFromSiblings(child);
1154 child->m_parent = parent->m_parent;
1155 if (parent->m_parent != 0) // parent is not the root.
1156 exchangeNodes(parent,child);
1157 else
1159 exchangeNodes(parent,child);
1160 m_root = child;
1162 destroyNode(parent);
1163 return true;
1165 else
1166 return false;
1170 /************************************************************************
1171 Cleanup
1172 ************************************************************************/
1175 * The function Cleanup() removes the entire PQ-tree, stored in the
1176 * class template PQTree. The function Cleanup() is called by the
1177 * destructor of the class template PQTree.
1178 * It scans all nodes of the tree and frees the
1179 * memory used by the tree. Cleanup() includes the removal of the memory
1180 * allocated by the following datastructures:
1181 * - \a m_root,
1182 * - \a m_pseudoRoot,
1183 * - \a m_pertinentNodes.
1184 * The function Cleanup() enables the client to reuse the function
1185 * Initialize().
1187 * In order to free the allocated memory, all nodes of the
1188 * tree have to be deleted, hence there destructors are called.
1189 * In order to achieve this, we start at the root of the tree and go down the
1190 * tree to the leaves for reaching every node. When a node is processed,
1191 * (besides the \a m_root, this will always be the node \a checkNode)
1192 * the pointers of all its children are stored in a queue \a helpqueue and
1193 * then the processed node is deleted.
1195 * The use of a queue \a helpqueue is a must, since the nodes do not
1196 * have pointers to all of their children, as the children mostly do
1197 * not have a pointer to their parent.
1199 * It might look weird at the first glance that the function Cleanup()
1200 * calls the function emptyAllPertinentNodes(), but if some nodes were removed
1201 * during a reduction, they were stored in the stack \a m_pertinentNodes.
1202 * These nodes have to be deleted as well
1203 * which is provided by the function emptyAllPertinentNodes().
1206 template<class T,class X,class Y>
1207 void PQTree<T,X,Y>::Cleanup()
1209 PQNode<T,X,Y>* nextSon = 0;
1210 PQNode<T,X,Y>* lastSon = 0;
1211 PQNode<T,X,Y>* oldSib = 0;
1213 Queue<PQNode<T,X,Y>*> helpqueue;
1215 if (m_root != 0)
1217 emptyAllPertinentNodes();
1220 Process the [[m_root]] of the [[PQTree]]. Before deleting [[m_root]],
1221 pointers to all its children are stored in the queue [[helpqueue]].
1223 if (m_root->type() == PQNodeRoot::PNode)
1225 if (m_root->m_referenceChild != 0)
1227 PQNode<T,X,Y>* firstSon = m_root->m_referenceChild;
1228 helpqueue.append(firstSon);
1230 if (firstSon->m_sibRight != 0)
1231 nextSon = firstSon->m_sibRight;
1232 while (nextSon != firstSon)
1234 helpqueue.append(nextSon);
1235 nextSon = nextSon->m_sibRight;
1239 else if (m_root->type() == PQNodeRoot::QNode)
1241 PQNode<T,X,Y>* firstSon = m_root->m_leftEndmost;
1242 helpqueue.append(firstSon);
1244 lastSon = m_root->m_rightEndmost;
1245 helpqueue.append(lastSon);
1247 nextSon = lastSon->getNextSib(oldSib);
1248 oldSib = lastSon;
1249 while (nextSon != firstSon)
1251 helpqueue.append(nextSon);
1252 PQNode<T,X,Y>* holdSib = nextSon->getNextSib(oldSib);
1253 oldSib = nextSon;
1254 nextSon = holdSib;
1259 CleanNode(m_root);
1260 delete m_root;
1262 while (!helpqueue.empty())
1264 PQNode<T,X,Y>* checkNode = helpqueue.pop();
1267 Process an arbitrary node [[checkNode]] of the [[PQTree]].
1268 Before deleting [[checkNode]],
1269 pointers to all its children are stored in the queue [[helpqueue]].
1271 if (checkNode->type() == PQNodeRoot::PNode)
1273 if (checkNode->m_referenceChild != 0)
1275 PQNode<T,X,Y>* firstSon = checkNode->m_referenceChild;
1276 helpqueue.append(firstSon);
1278 if (firstSon->m_sibRight != 0)
1279 nextSon = firstSon->m_sibRight;
1280 while (nextSon != firstSon)
1282 helpqueue.append(nextSon);
1283 nextSon = nextSon->m_sibRight;
1287 else if (checkNode->type() == PQNodeRoot::QNode)
1289 oldSib = 0;
1291 PQNode<T,X,Y>*firstSon = checkNode->m_leftEndmost;
1292 helpqueue.append(firstSon);
1294 lastSon = checkNode->m_rightEndmost;
1295 helpqueue.append(lastSon);
1297 nextSon = lastSon->getNextSib(oldSib);
1298 oldSib = lastSon;
1299 while (nextSon != firstSon)
1301 helpqueue.append(nextSon);
1302 PQNode<T,X,Y>* holdSib = nextSon->getNextSib(oldSib);
1303 oldSib = nextSon;
1304 nextSon = holdSib;
1308 CleanNode(checkNode);
1309 delete checkNode;
1313 CleanNode(m_pseudoRoot);
1314 delete m_pseudoRoot;
1316 delete m_pertinentNodes;
1318 m_root = 0;
1319 m_pertinentRoot = 0;
1320 m_pseudoRoot = 0;
1321 m_pertinentNodes = 0;
1323 m_numberOfLeaves = 0;
1324 m_identificationNumber = 0;
1328 /************************************************************************
1329 clientPrintNodeCategorie
1330 ************************************************************************/
1333 * If the user wishes to use different flags in a derived class of PQTree
1334 * that are not available in this implementation, he can overload the function
1335 * clientPrintNodeCategorie(). This function is called per default by the functions
1336 * printOutCurrentTree() and printNode().
1337 * With the help of this function it is possible to influence the layout of the nodes
1338 * by using new, different lables depicting node categories
1339 * in the <em>Tree Interface</em>.
1342 template<class T,class X,class Y>
1343 int PQTree<T,X,Y>::clientPrintNodeCategorie(PQNode<T,X,Y>* nodePtr)
1345 return (nodePtr != 0) ? 1 : 0;
1346 // 1 is the standard node categrie in the Tree Interface.
1350 /************************************************************************
1351 clientPrintStatus
1352 ************************************************************************/
1355 * If the user wishes to use different status in a derived class of PQTree
1356 * that are not available in this implementation, he can overload the function
1357 * clientPrintStatus(). This function is called per default by the functions
1358 * printOutCurrentTree() and printNode().
1359 * With the help of this function it is possible to influence the information stored
1360 * at nodes in the <em>Tree Interface</em> that concern the
1361 * status of a node.
1364 template<class T,class X,class Y>
1365 const char* PQTree<T,X,Y>::clientPrintStatus(PQNode<T,X,Y>* nodePtr)
1367 return (nodePtr != 0) ? "ERROR" : "ERROR: clientPrintStatus: NO NODE ACCESSED";
1371 /************************************************************************
1372 clientPrintType
1373 ************************************************************************/
1376 * If the user wishes to use different types in a derived class of PQTree
1377 * that are not available in this implementation, he can overload the function
1378 * clientPrintType(). This function is called per default by the functions
1379 * printOutCurrentTree() and printNode().
1380 * With the help of this function it is possible to influence the information stored
1381 * at nodes in the <em>Tree Interface</em> that concern the
1382 * type of a node.
1385 template<class T,class X,class Y>
1386 const char* PQTree<T,X,Y>::clientPrintType(PQNode<T,X,Y>* nodePtr)
1388 return (nodePtr != 0) ? "ERROR" : "ERROR: clientPrintType: NO NODE ACCESSED";
1392 /************************************************************************
1393 Constructor
1394 ************************************************************************/
1397 template<class T,class X,class Y> PQTree<T,X,Y>::PQTree()
1399 m_root = 0;
1400 m_pertinentRoot = 0;
1401 m_pseudoRoot = 0;
1403 m_numberOfLeaves = 0;
1404 m_identificationNumber = 0;
1406 m_pertinentNodes = 0;
1411 /************************************************************************
1412 copyFullChildrenToPartial
1413 ************************************************************************/
1416 * The function copyFullChildrenToPartial()
1417 * copies all full children of \a nodePtr to a new P-node
1418 * The node \a nodePtr has to be a P-node. The new P-node
1419 * is added to \a partialChild as an endmost child of \a partialChild.
1420 * The node \a partialChild has to be a Q-node and the new P-node is added
1421 * to the side of \a partialChild where the pertinent children are.
1423 * The new P-node is allocated by this function and referenced by the
1424 * variable \a newNode.
1426 * The function copyFullChildrenToPartial() is used by the functions
1427 * templateP4(), templateP5(), and templateP6().
1430 template<class T,class X,class Y>
1431 void PQTree<T,X,Y>::copyFullChildrenToPartial(
1432 PQNode<T,X,Y> *nodePtr,
1433 PQNode<T,X,Y> *partialChild)
1435 if (nodePtr->fullChildren->size() > 0)
1436 // There are some full children to
1437 // be copied.
1439 nodePtr->m_childCount = nodePtr->m_childCount -
1440 nodePtr->fullChildren->size();
1442 PQNode<T,X,Y> *newNode = createNodeAndCopyFullChildren(nodePtr->fullChildren);
1444 // Introduce newNode as endmost
1445 // child of the partial Q-node.
1446 partialChild->m_childCount++;
1447 partialChild->fullChildren->pushFront(newNode);
1449 if (clientLeftEndmost(partialChild)->status() == PQNodeRoot::FULL)
1451 PQNode<T,X,Y> *checkNode = partialChild->m_leftEndmost;
1452 partialChild->m_leftEndmost = newNode;
1453 linkChildrenOfQnode(checkNode,newNode);
1456 else {
1457 // ERROR: Endmostchild not found?
1458 OGDF_ASSERT(clientRightEndmost(partialChild)->status() == PQNodeRoot::FULL);
1460 PQNode<T,X,Y> *checkNode = partialChild->m_rightEndmost;
1461 partialChild->m_rightEndmost = newNode;
1462 linkChildrenOfQnode(checkNode,newNode);
1465 newNode->m_parent = partialChild;
1466 newNode->m_parentType = PQNodeRoot::QNode;
1471 /************************************************************************
1472 createNodeAndCopyFullChildren
1473 ************************************************************************/
1476 * The function createNodeAndCopyFullChildren() copies the full children of a
1477 * P-node that are stored in the stack \a fullNodes to a new P-node.
1478 * This new P-node
1479 * is created by the function and stored in \a newNode if there is more than one full child.
1480 * If there is just one full child, it is not necessary to construct a new
1481 * P-node and the full child is stored in \a newNode.
1482 * The \a newNode is the return value of the procedure.
1484 * The function createNodeAndCopyFullChildren() is used by
1485 * templateP2() templateP3() and the function copyFullChildrenToPartial().
1486 * The function createNodeAndCopyFullChildren() uses the following
1487 * variables.
1488 * - \a newNode stores the adress of the new allocated P-node or
1489 * the adress of the only full child.
1490 * - \a oldSon is a variable used for adding the full nodes as
1491 * children to the new P-node.
1492 * - \a firstSon stores the adress of the first detected full
1493 * child. It is needed for adding the full nodes as
1494 * children to the new P-node.
1495 * - \a checkSon is a variable used for adding the full nodes as
1496 * children to the new P-node.
1497 * - \a newPQnode is used for proper allocation of the new P-node.
1500 template<class T,class X,class Y>
1501 PQNode<T,X,Y>* PQTree<T,X,Y>::createNodeAndCopyFullChildren(
1502 List<PQNode<T,X,Y>*> *fullNodes)
1504 PQNode<T,X,Y> *newNode = 0;
1506 if (fullNodes->size() == 1)
1509 There is just one full child. So no new $P$-node is created. The
1510 full child is copied as child to the [[partialChild]].
1512 newNode = fullNodes->popFrontRet();
1513 removeChildFromSiblings(newNode);
1516 else
1519 This chunk belongs to the function [[createNodeAndCopyFullChildren]].
1520 There is more than one full child, so a new $P$-node is created.
1521 This chunk first allocates the memory for the new $P$-node that will
1522 be stored in [[newNode]]. Then it pops the nodes out of the stack
1523 [[fullNodes]] and introduces them as sons of [[newNode]].
1524 Popping the nodes out of the stack implies at the same time
1525 that they are removed from the [[fullChildren]] stack of the
1526 $P$-node of their parent.
1528 newNode = OGDF_NEW PQInternalNode<T,X,Y>(m_identificationNumber++,PQNodeRoot::PNode,PQNodeRoot::FULL);
1529 m_pertinentNodes->pushFront(newNode);
1530 newNode->m_pertChildCount = fullNodes->size();
1531 newNode->m_childCount = fullNodes->size();
1534 The first node is copied separately, since we need the pointer to it
1535 for setting the pointers to the siblings of the next full nodes.
1537 PQNode<T,X,Y> *firstSon = fullNodes->popFrontRet();
1538 removeChildFromSiblings(firstSon);
1539 newNode->fullChildren->pushFront(firstSon);
1540 firstSon->m_parent = newNode;
1541 firstSon->m_parentType = newNode->type();
1542 PQNode<T,X,Y> *oldSon = firstSon;
1546 All remaining nodes that are stored in the stack [[fullNodes]] are
1547 introduced as children of the new $P$-node [[newNode]]. Observe
1548 that the children of a $P$-node must form a doubly linked list.
1549 Hence the last node and the [[firstSon]] must be linked via their
1550 siblings pointers.
1552 while (!fullNodes->empty())
1554 PQNode<T,X,Y> *checkSon = fullNodes->popFrontRet();
1555 removeChildFromSiblings(checkSon);
1556 newNode->fullChildren->pushFront(checkSon);
1557 oldSon->m_sibRight = checkSon;
1558 checkSon->m_sibLeft = oldSon;
1559 checkSon->m_parent = newNode;
1560 checkSon->m_parentType = newNode->type();
1561 oldSon = checkSon;
1563 firstSon->m_sibLeft = oldSon;
1564 oldSon->m_sibRight = firstSon;
1565 newNode->m_referenceChild = firstSon;
1566 firstSon->m_referenceParent = newNode;
1569 return newNode;
1573 /************************************************************************
1574 emptyAllPertinetNodes
1575 ************************************************************************/
1578 * The function emptyAllPertinentNodes() has to be called after a reduction
1579 * has been processed. In cleans up all flags that have been set in the
1580 * pertinent nodes during the reduction process. All pertinent nodes have been
1581 * stored in the private member stack \a m_pertinentNodes of the class template
1582 * PQTree during the Bubble()-phase
1583 * or when processing one of the templates (see templateL1() to templateQ3()).
1586 template<class T,class X,class Y>
1587 void PQTree<T,X,Y>::emptyAllPertinentNodes()
1589 PQNode<T,X,Y> *nodePtr;
1591 while(!m_pertinentNodes->empty())
1593 nodePtr = m_pertinentNodes->popFrontRet();
1594 switch (nodePtr->status())
1596 case PQNodeRoot::TO_BE_DELETED:
1597 if (nodePtr == m_root)
1598 m_root = 0;
1599 CleanNode(nodePtr);
1600 //if (nodePtr)
1601 delete nodePtr;
1602 break;
1604 case PQNodeRoot::FULL:
1605 emptyNode(nodePtr);
1606 break;
1608 case PQNodeRoot::PARTIAL:
1609 emptyNode(nodePtr);
1610 break;
1612 default:
1613 clientDefinedEmptyNode(nodePtr);
1614 break;
1617 m_pseudoRoot->m_pertChildCount = 0;
1618 m_pseudoRoot->m_pertLeafCount = 0;
1619 m_pseudoRoot->fullChildren->clear();
1620 m_pseudoRoot->partialChildren->clear();
1621 m_pseudoRoot->status(PQNodeRoot::EMPTY);
1622 m_pseudoRoot->mark(PQNodeRoot::UNMARKED);
1626 /************************************************************************
1627 emptyNode
1628 ************************************************************************/
1631 * The funtion emptyNode() cleans up all stacks, flags and pointers of a
1632 * pertinent node that has been visited during the reduction process.
1635 template<class T,class X,class Y>
1636 void PQTree<T,X,Y>::emptyNode(PQNode<T,X,Y> *nodePtr)
1638 nodePtr->status(PQNodeRoot::EMPTY);
1639 nodePtr->m_pertChildCount = 0;
1640 nodePtr->m_pertLeafCount = 0;
1641 nodePtr->fullChildren->clear();
1642 nodePtr->partialChildren->clear();
1643 nodePtr->mark(PQNodeRoot::UNMARKED);
1647 /************************************************************************
1648 exchangeNodes
1649 ************************************************************************/
1652 * The function exchangeNodes() replaces the \a oldNode by the \a newNode
1653 * in the tree. This is a function used very often in the template matchings,
1654 * normally in combination with the construction of a new node which has to
1655 * conquer the place of an existing node in the tree.
1657 * This function can be used in all cases, so the parent of \a oldNode
1658 * is allowed to be either a Q-node or a P-node and \a oldNode may be
1659 * any child of its parent.
1661 * The client should observe, that this function does \b not reset
1662 * the pointer \a m_root. If necessary, this has to be done explicitly by
1663 * the client himself.
1666 template<class T,class X,class Y>
1667 void PQTree<T,X,Y>::exchangeNodes(
1668 PQNode<T,X,Y> *oldNode,
1669 PQNode<T,X,Y> *newNode)
1671 if (oldNode->m_referenceParent != 0)
1674 The node [[oldNode]] is connected to its parent
1675 via the reference pointer of the doubly linked list. The [[newNode]]
1676 will be the new reference child and is linked via the reference
1677 pointers to the $P$-node.
1679 oldNode->m_referenceParent->m_referenceChild = newNode;
1680 newNode->m_referenceParent = oldNode->m_referenceParent;
1681 oldNode->m_referenceParent = 0;
1684 else if (oldNode->endmostChild())
1687 The [[oldNode]] is endmost child of a Q-node. So its parent
1688 contains an extra pointer to [[oldNode]]. Link the parent of
1689 [[oldNode]] to [[newNode]] via this pointer and make [[newNode]]
1690 endmost child of its new parent.
1692 if (oldNode->m_parent->m_leftEndmost == oldNode)
1693 oldNode->m_parent->m_leftEndmost = newNode;
1694 else if (oldNode->m_parent->m_rightEndmost == oldNode)
1695 oldNode->m_parent->m_rightEndmost = newNode;
1698 if ((oldNode->m_sibLeft == oldNode) && (oldNode->m_sibRight == oldNode))
1701 Two possible cases are occured.
1702 \begin{enumerate}
1703 \item [[oldNode]] is the only child of a $P$-node. In order to
1704 implement the doubly linked list of children of the $P$-node, the sibling
1705 pointers of [[newNode]] are set to [[newNode]].
1706 \item [[oldNode]] is the [[m_root]] of the $PQ$-tree. Since
1707 by our definition of the $PQ$-tree the sibling pointers of the
1708 [[m_root]] point to the root itself, (i.e. to make sure that
1709 checking for the endmost child property is also valid for the root)
1710 the sibling pointers of [[newNode]] are set to [[newNode]] as well.
1711 \end{enumerate}
1713 oldNode->m_sibLeft = 0;
1714 oldNode->m_sibRight = 0;
1715 if (oldNode->m_parent == 0)
1717 newNode->m_sibLeft = newNode;
1718 newNode->m_sibRight = newNode;
1720 else
1722 newNode->m_sibLeft = newNode;
1723 newNode->m_sibRight = newNode;
1726 else
1728 OGDF_ASSERT(!(oldNode->m_sibLeft == oldNode))
1729 //sibling pointers of old node are not compatible
1730 OGDF_ASSERT(!(oldNode->m_sibRight == oldNode))
1731 //sibling pointers of old node are not compatible.
1734 Manage the exchange of [[oldNode]] and [[newNode]] according to
1735 [[oldNode]]'s siblings. The chunk checks both siblings of
1736 [[oldNode]] and resets the sibling pointers of [[oldNode]]'s siblings
1737 as well as the sibling pointers of [[newNode]].
1739 if (oldNode->m_sibLeft != 0)
1741 if (oldNode->m_sibLeft->m_sibRight == oldNode)
1742 oldNode->m_sibLeft->m_sibRight = newNode;
1743 else {
1744 // Sibling was not connected to child?
1745 OGDF_ASSERT(oldNode->m_sibLeft->m_sibLeft == oldNode);
1746 oldNode->m_sibLeft->m_sibLeft = newNode;
1748 newNode->m_sibLeft = oldNode->m_sibLeft;
1749 oldNode->m_sibLeft = 0;
1752 if (oldNode->m_sibRight != 0)
1754 if (oldNode->m_sibRight->m_sibLeft == oldNode)
1755 oldNode->m_sibRight->m_sibLeft = newNode;
1756 else {
1757 // Sibling was not connected to child?
1758 OGDF_ASSERT(oldNode->m_sibRight->m_sibRight == oldNode);
1759 oldNode->m_sibRight->m_sibRight = newNode;
1761 newNode->m_sibRight = oldNode->m_sibRight;
1762 oldNode->m_sibRight = 0;
1765 newNode->m_parentType = oldNode->m_parentType;
1766 newNode->m_parent = oldNode->m_parent;
1770 /************************************************************************
1771 front
1772 ************************************************************************/
1775 * The function front()
1776 * returns the keys stored in the leaves of the front of
1777 * \a nodePtr. A specified node \a nodePtr of the PQ-tree is
1778 * handed to the function and front() detects the leaves in the front
1779 * of this node returning the elements represented by the leaves. These
1780 * elements are
1781 * stored in an array of keys named \a leafKeys.
1782 * The return value is the numbers of leaves that have been detected.
1783 * Observe that front() uses \a leafKeys[0] to store the
1784 * first key.
1787 template<class T,class X,class Y>
1788 void PQTree<T,X,Y>::front(
1789 PQNode<T,X,Y>* nodePtr,
1790 SListPure<PQLeafKey<T,X,Y>*> &leafKeys)
1792 Queue<PQNode<T,X,Y>*> helpqueue;
1793 helpqueue.append(nodePtr);
1795 while (!helpqueue.empty())
1797 PQNode<T,X,Y>* checkNode = helpqueue.pop();
1799 if (checkNode->type() == PQNodeRoot::leaf)
1800 leafKeys.pushBack(checkNode->getKey());
1801 else
1803 PQNode<T,X,Y>* firstSon = 0;
1804 PQNode<T,X,Y>* nextSon = 0;
1805 PQNode<T,X,Y>* oldSib = 0;
1806 PQNode<T,X,Y>* holdSib = 0;
1808 if (checkNode->type() == PQNodeRoot::PNode)
1810 OGDF_ASSERT(checkNode->m_referenceChild)
1811 firstSon = checkNode->m_referenceChild;
1813 else if (checkNode->type() == PQNodeRoot::QNode)
1815 OGDF_ASSERT(checkNode->m_leftEndmost)
1816 firstSon = checkNode->m_leftEndmost;
1818 helpqueue.append(firstSon);
1819 nextSon = firstSon->getNextSib(oldSib);
1820 oldSib = firstSon;
1821 while (nextSon && nextSon != firstSon)
1823 helpqueue.append(nextSon);
1824 holdSib = nextSon->getNextSib(oldSib);
1825 oldSib = nextSon;
1826 nextSon = holdSib;
1833 /************************************************************************
1834 Initialize
1835 ************************************************************************/
1838 * The function Initialize() initializes the PQ-tree with a set of elements.
1839 * These elements have to be template classes of the class template PQLeafKey
1840 * and are handed to the function in an array \a leafKeys.
1841 * The function constructs the universal PQ-tree. If the
1842 * \a numberOfElements > 1, the universal PQ-tree consists of one P-node
1843 * as root (stored in \a m_root) and all leaves gathered underneath the P-node,
1844 * symbolizing all kinds of permutations. If \a numberOfElements = 1,
1845 * the universal PQ-tree consists of a single PQLeaf, being the root of
1846 * the tree.
1848 * Observe that the first element has to be stored in
1849 * \a leafKeys[0] and the last one in
1850 * \a leafKeys[\a numberOfElements-1].
1851 * The function Initialize() returns 1, if the initialization of
1852 * the PQ-tree was successful.
1855 template<class T,class X,class Y>
1856 int PQTree<T,X,Y>::Initialize(SListPure<PQLeafKey<T,X,Y>*> &leafKeys)
1858 m_pertinentNodes = OGDF_NEW List<PQNode<T,X,Y>*>;
1860 if (!leafKeys.empty())
1862 PQInternalNode<T,X,Y> *newNode2 = OGDF_NEW PQInternalNode<T,X,Y>(-1,PQNodeRoot::QNode,PQNodeRoot::PARTIAL);
1863 m_pseudoRoot = newNode2;
1865 if (leafKeys.begin() != leafKeys.end()) // at least two elements
1867 PQInternalNode<T,X,Y> *newNode = OGDF_NEW PQInternalNode<T,X,Y>(m_identificationNumber++,PQNodeRoot::PNode,PQNodeRoot::EMPTY);
1868 m_root = newNode;
1869 m_root->m_sibLeft = m_root;
1870 m_root->m_sibRight = m_root;
1871 return addNewLeavesToTree(newNode,leafKeys);
1873 PQLeaf<T,X,Y> *newLeaf = OGDF_NEW PQLeaf<T,X,Y>(m_identificationNumber++,PQNodeRoot::EMPTY,*leafKeys.begin());
1874 m_root = newLeaf;
1875 m_root->m_sibLeft = m_root;
1876 m_root->m_sibRight = m_root;
1877 return 1;
1880 return 0;
1884 /************************************************************************
1885 linkChildrenOfQnode
1886 ************************************************************************/
1889 * The function linkChildrenOfQnode() links the two endmost children
1890 * of two \b different Q-nodes via their sibling pointers together.
1891 * The purpose of doing this is to combine the children of two Q-nodes
1892 * as children of only one Q-node. This function does not reset the
1893 * pointers to the endmost children of the Q-node. This has to be done
1894 * by the client of the function.
1897 template<class T,class X,class Y>
1898 void PQTree<T,X,Y>::linkChildrenOfQnode(
1899 PQNode<T,X,Y> *installed,
1900 PQNode<T,X,Y> *newChild)
1902 if ((installed != 0) && (newChild != 0))
1904 if (installed->m_sibLeft == 0)
1906 installed->m_sibLeft = newChild;
1907 if (newChild->m_sibRight == 0)
1908 newChild->m_sibRight = installed;
1909 else
1910 newChild->m_sibLeft = installed;
1912 else {
1913 // endmost child with 2 siblings encountered?
1914 OGDF_ASSERT(installed->m_sibRight == 0);
1916 installed->m_sibRight = newChild;
1917 if (newChild->m_sibLeft == 0)
1918 newChild->m_sibLeft = installed;
1919 else
1920 newChild->m_sibRight = installed;
1927 /************************************************************************
1928 writeGML
1929 ************************************************************************/
1932 * The function writeGML() prints the PQ-tree in the GML
1933 * fileformat. The filename is ended by a ".gml" and can be read
1934 * eg. by the <em>AGD</em>.
1937 template<class T,class X,class Y>
1938 void PQTree<T,X,Y>::writeGML(const char *fileName)
1940 ofstream os(fileName);
1941 writeGML(os);
1944 template<class T,class X,class Y>
1945 void PQTree<T,X,Y>::writeGML(ostream &os)
1947 Array<int> id(0,m_identificationNumber,0);
1948 int nextId = 0;
1950 SListPure<PQNode<T,X,Y>*> helpQueue;
1951 SListPure<PQNode<T,X,Y>*> secondTrace;
1953 os.setf(ios::showpoint);
1954 os.precision(10);
1956 os << "Creator \"ogdf::PQTree::writeGML\"\n";
1957 os << "graph [\n";
1958 os << " directed 1\n";
1960 PQNode<T,X,Y>* checkNode = m_root;
1961 PQNode<T,X,Y>* firstSon = 0;
1962 PQNode<T,X,Y>* nextSon = 0;
1963 PQNode<T,X,Y>* lastSon = 0;
1964 PQNode<T,X,Y>* oldSib = 0;
1965 PQNode<T,X,Y>* holdSib = 0;
1967 if (checkNode->type() != PQNodeRoot::leaf)
1968 secondTrace.pushBack(checkNode);
1970 while (checkNode)
1972 os << " node [\n";
1974 os << " id " << (id[checkNode->m_identificationNumber] = nextId++) << "\n";
1976 os << " label \"" << checkNode->m_identificationNumber;
1977 if (checkNode->getKey() != 0)
1978 checkNode->getKey()->print(os);
1979 os << "\"\n";
1981 os << " graphics [\n";
1982 if (m_root->status() == PQNodeRoot::FULL)
1984 if (checkNode->type() == PQNodeRoot::PNode)
1985 os << " fill \"#FF0000\"\n";
1986 else if (checkNode->type() == PQNodeRoot::QNode)
1987 os << " fill \"#0000A0\"\n";
1988 else if (checkNode->type() == PQNodeRoot::leaf)
1989 os << "fill \"#FFFFE6\"\n";
1991 else if (m_root->status() == PQNodeRoot::EMPTY)
1993 if (checkNode->type() == PQNodeRoot::PNode)
1994 os << " fill \"#FF0000\"\n";
1995 else if (checkNode->type() == PQNodeRoot::QNode)
1996 os << " fill \"#0000A0\"\n";
1997 else if (checkNode->type() == PQNodeRoot::leaf)
1998 os << " fill \"#00FF00\"\n";
2000 else if (m_root->status() == PQNodeRoot::PARTIAL)
2002 if (checkNode->type() == PQNodeRoot::PNode)
2003 os << " fill \"#FF0000\"\n";
2004 else if (checkNode->type() == PQNodeRoot::QNode)
2005 os << " fill \"#0000A0\"\n";
2006 else if (checkNode->type() == PQNodeRoot::leaf)
2007 os << " fill \"#FFFFE6\"\n";
2009 else if (m_root->status() == PQNodeRoot::PERTINENT)
2011 if (checkNode->type() == PQNodeRoot::PNode)
2012 os << " fill \"#FF0000\"\n";
2013 else if (checkNode->type() == PQNodeRoot::QNode)
2014 os << " fill \"#0000A0\"\n";
2015 else if (checkNode->type() == PQNodeRoot::leaf)
2016 os << " fill \"#FFFFE6\"\n";
2019 os << " ]\n"; // graphics
2020 os << " ]\n"; // node
2022 if (checkNode->type() == PQNodeRoot::PNode)
2024 if (checkNode->m_referenceChild != 0)
2026 firstSon = checkNode->m_referenceChild;
2027 helpQueue.pushBack(firstSon);
2029 if (firstSon->m_sibRight != 0)
2030 nextSon = firstSon->m_sibRight;
2031 while (nextSon != firstSon)
2033 helpQueue.pushBack(nextSon);
2034 nextSon = nextSon->m_sibRight;
2038 else if (checkNode->type() == PQNodeRoot::QNode)
2040 oldSib = 0;
2041 holdSib = 0;
2043 firstSon = checkNode->m_leftEndmost;
2044 helpQueue.pushBack(firstSon);
2046 lastSon = checkNode->m_rightEndmost;
2047 if ( firstSon != lastSon)
2049 helpQueue.pushBack(lastSon);
2050 nextSon = lastSon->getNextSib(oldSib);
2051 oldSib = lastSon;
2052 while (nextSon != firstSon)
2054 helpQueue.pushBack(nextSon);
2055 holdSib = nextSon->getNextSib(oldSib);
2056 oldSib = nextSon;
2057 nextSon = holdSib;
2061 if (!helpQueue.empty())
2063 checkNode = helpQueue.popFrontRet();
2064 if (checkNode->type() != PQNodeRoot::leaf)
2065 secondTrace.pushBack(checkNode);
2067 else
2068 checkNode = 0;
2072 SListIterator<PQNode<T,X,Y>*> it;
2074 for (it = secondTrace.begin(); it.valid(); it++)
2076 checkNode = *it;
2077 if (checkNode->type() == PQNodeRoot::PNode)
2079 if (checkNode->m_referenceChild != 0)
2081 firstSon = checkNode->m_referenceChild;
2082 os << " edge [\n";
2083 os << " source " << id[checkNode->m_identificationNumber] << "\n";
2084 os << " target " << id[firstSon->m_identificationNumber] << "\n";
2085 os << " ]\n"; // edge
2087 if (firstSon->m_sibRight != 0)
2088 nextSon = firstSon->m_sibRight;
2089 while (nextSon != firstSon)
2091 os << " edge [\n";
2092 os << " source " << id[checkNode->m_identificationNumber] << "\n";
2093 os << " target " << id[nextSon->m_identificationNumber] << "\n";
2094 os << " ]\n"; // edge
2095 nextSon = nextSon->m_sibRight;
2099 else if (checkNode->type() == PQNodeRoot::QNode)
2101 oldSib = 0;
2102 holdSib = 0;
2104 firstSon = checkNode->m_leftEndmost;
2105 lastSon = checkNode->m_rightEndmost;
2107 os << " edge [\n";
2108 os << " source " << id[checkNode->m_identificationNumber] << "\n";
2109 os << " target " << id[lastSon->m_identificationNumber] << "\n";
2110 os << " ]\n"; // edge
2111 if ( firstSon != lastSon)
2113 nextSon = lastSon->getNextSib(oldSib);
2114 os << " edge [\n";
2115 os << " source " << id[checkNode->m_identificationNumber] << "\n";
2116 os << " target " << id[nextSon->m_identificationNumber] << "\n";
2117 os << " ]\n"; // edge
2119 oldSib = lastSon;
2120 while (nextSon != firstSon)
2122 holdSib = nextSon->getNextSib(oldSib);
2123 oldSib = nextSon;
2124 nextSon = holdSib;
2125 os << " edge [\n";
2126 os << " source " << id[checkNode->m_identificationNumber] << "\n";
2127 os << " target " << id[nextSon->m_identificationNumber] << "\n";
2128 os << " ]\n"; // edge
2133 os << "]\n"; // graph
2138 /************************************************************************
2139 Reduce
2140 ************************************************************************/
2143 * The function Reduce() does the reduction of the pertinent leaves
2144 * with the help of the template matchings, designed by Booth and Lueker.
2145 * The reader should observe that this function can only be called after
2146 * every pertinent node in the pertinent subtree has gotten a valid parent
2147 * pointer. If this is not the case, the programm will be interrupted
2148 * by run-time errors such as seqmentation faults. The pertinent nodes
2149 * can get valid parent pointers by using the function Bubble().
2150 * If the function Bubble() returns 1, then it was succesful in
2151 * giving each pertinent node in the pertinent subtree a valid parent pointer.
2152 * If the function returns 0, then some nodes do not have a valid
2153 * parent pointer and the pertinent leaves are not reducable.
2155 * The function Reduce() starts with the pertinent leaves and stores
2156 * them in
2157 * a queue \a processNodes. Every time a node is processed, its parent is
2158 * checked whether all its pertinent children are already processed.
2159 * If this is the case, the parent is allowed to be processed as well
2160 * and stored in the queue.
2162 * Processing a node means that the function Reduce() tries to apply
2163 * one of the template matchings. In case that one template matching was
2164 * successful, the node was reduced and Reduce() tries to reduce the
2165 * next node.
2166 * In case that no template matching was successfully applied, the tree is
2167 * is irreducible. This causes the reduction process to be halted
2168 * returning 0.
2170 * The folllowing variables are used by the function Reduce().
2171 * - \a checkLeaf is a pointer to a various PQLeaf of the set of
2172 * elements that has to be reduced.
2173 * - \a checkNode is a pointer to a various node of the pertinent
2174 * subtree.
2175 * - \a pertLeafCount counts the number of pertinent leaves in the
2176 * PQ-tree. Since Reduce() takes care that every node knows the
2177 * number of pertinent leaves in its frontier, the root of the
2178 * pertinent subtree can be identified with the help of \a pertLeafCount.
2179 * - \a processNodes is a queue storing nodes of the pertinent
2180 * subtree that are considered to be reduced next. A node may be
2181 * reduced (and therefore is pushed on to \a processNodes) as soon as
2182 * all its pertinent children have been reduced.
2185 template<class T,class X,class Y>
2186 bool PQTree<T,X,Y>::Reduce(SListPure<PQLeafKey<T,X,Y>*> &leafKeys)
2188 int pertLeafCount = 0;
2189 Queue<PQNode<T,X,Y>*> processNodes;
2192 In a first step the pertinent leaves have to be identified in the tree
2193 and are entered on to the queue [[processNodes]]. The identification of
2194 the leaves can be done with the help of a pointer stored in every
2195 [[PQLeafKey]] in constant time for every element.
2197 SListIterator<PQLeafKey<T,X,Y>*> it;
2198 for (it = leafKeys.begin(); it.valid(); ++it)
2200 PQNode<T,X,Y>* checkLeaf = (*it)->nodePointer();
2201 checkLeaf->status(PQNodeRoot::FULL);
2202 checkLeaf->m_pertLeafCount = 1;
2203 processNodes.append(checkLeaf);
2204 pertLeafCount++;
2207 PQNode<T,X,Y>* checkNode = processNodes.top();
2208 while ((checkNode != 0) && (processNodes.size() > 0))
2210 checkNode = processNodes.pop();
2212 if (checkNode->m_pertLeafCount < pertLeafCount)
2215 Application of the template matchings to a pointer [[checkNode]]
2216 storing the adress of a node that is {\bf not the root} of the
2217 pertinent subtree. Before applying the template matchings to
2218 [[checkNode]], some values of the parent of [[checkNode]] are
2219 updated. The number of the parents pertinent children stored in
2220 [[pertChildCount]] is count down by one. In case that
2221 [[checkNode->m_parent->m_pertChildCount == 0]], we know that all
2222 pertinent children of the parent have been processed. Since the
2223 parent then is allowed to be processed as well,
2224 [[checkNode->m_parent]] is stored in the queue [[processNodes]].
2226 checkNode->m_parent->m_pertLeafCount =
2227 checkNode->m_parent->m_pertLeafCount
2228 + checkNode->m_pertLeafCount;
2230 checkNode->m_parent->m_pertChildCount--;
2231 if (!checkNode->m_parent->m_pertChildCount)
2232 processNodes.append(checkNode->m_parent);
2233 if (!templateL1(checkNode,0))
2234 if (!templateP1(checkNode,0))
2235 if (!templateP3(checkNode))
2236 if (!templateP5(checkNode))
2237 if (!templateQ1(checkNode,0))
2238 if (!templateQ2(checkNode,0))
2239 checkNode= 0;
2241 else
2244 application of the template matchings to a pointer [[checkNode]]
2245 that stores the adress of a node that {\bf is the root} of the
2246 pertinent subtree. In a case that a template matching was
2247 successfully applied, the pointer [[checkNode]] stores after the
2248 application the adress of the root of pertinent subtree. This
2249 includes nodes that have been newly introduced as root of the
2250 perinent subtree during the application. If no template matching
2251 was successfully applied [[checkNode]] is a [[0]] pointer.
2253 if (!templateL1(checkNode,1))
2254 if (!templateP1(checkNode,1))
2255 if (!templateP2(&checkNode))
2256 if (!templateP4(&checkNode))
2257 if (!templateP6(&checkNode))
2258 if (!templateQ1(checkNode,1))
2259 if (!templateQ2(checkNode,1))
2260 if (!templateQ3(checkNode))
2261 checkNode = 0;
2265 m_pertinentRoot = checkNode;
2266 return (m_pertinentRoot != 0);
2271 /************************************************************************
2272 Reduction
2273 ************************************************************************/
2276 * The function Reduction() tests whether permissible permutations of the
2277 * elements of U exist such that the elements of a subset S of U,
2278 * stored in \a leafKeys, form a consecutive sequence. If there exists
2279 * such a permutation, the PQ-tree is reduced and Reduction()
2280 * returns 1.
2282 * The function Reduction() gets a list \a leafKeys
2283 * of pointers to elements of type PQLeafKey,
2284 * representing all elements of S.
2286 * Reduction() calls the procedure Bubble() and if Bubble() was
2287 * successful, Reduction() calls the function Reduce().
2290 template<class T,class X,class Y>
2291 bool PQTree<T,X,Y>::Reduction(SListPure<PQLeafKey<T,X,Y>*> &leafKeys)
2293 bool success = Bubble(leafKeys);
2295 if (!success)
2296 return false;
2297 else
2298 return Reduce(leafKeys);
2303 /************************************************************************
2304 removeBlock
2305 ************************************************************************/
2308 * This chunk contains the procedure removeBlock. It is used by the functions
2309 * templateQ2() and templateQ3(). The node \a nodePtr is expected to be a
2310 * Q-node with no, one or at most two partial children, such that
2311 * the partial and full children of \a nodePtr form a legal consecutive
2312 * sequence, hence can be reduced.
2314 * The function removeBlock() does the
2315 * following: Of every partial node that is found in the sequence of children of
2316 * \a nodePtr, all children are removed from that partial node and included
2317 * as children of \a nodePtr, occupying the place of the partial node in
2318 * the sequence of children of \a nodePtr. Thereby, removeBlock() takes
2319 * care, that the newly included full children of \a nodePtr form
2320 * a consecutive sequence with the already existing pertinent children of
2321 * \a nodePtr. The partial node itself is deleted afterwards.
2324 template<class T,class X,class Y>
2325 void PQTree<T,X,Y>::removeBlock(PQNode<T,X,Y> *nodePtr,bool isRoot)
2329 For every
2330 partial child we keep a set of pointers. Since there are at most
2331 two partial children, we initialize two sets. Every set contains
2332 besides a pointer to the partial child four pointers to its endmost
2333 children, sorted according to their full or empty labels and pointers
2334 to the immediate siblings of the partial child, also sorted according
2335 to their full or empty labels.
2337 ///Pointer to the first partial child
2338 PQNode<T,X,Y> *partial_1 = 0;
2341 Pointer to the full endmost child (more
2342 precisely: to the endmost child appearing on the full side) of
2343 [[partial_1]]. In case that ignored nodes are used, this [[endfull_1]]
2344 may store the adress of an ignored node.
2346 PQNode<T,X,Y> *endfull_1 = 0;
2349 Pointer to the empty endmost child (more
2350 precisely: to the endmost child appearing on the empty side) of
2351 [[partial_1]]. In case that ignored nodes are used, this [[endempty_1]]
2352 may store the adress of an ignored node.
2354 PQNode<T,X,Y> *endempty_1 = 0;
2357 Pointer to the first {\it non ignored} node
2358 with full status. [[realfull_1]] is identical to [[endfull_1]] if no
2359 ignored nodes appear at the full end of the first partial child.
2361 PQNode<T,X,Y> *realfull_1 = 0;
2364 Pointer to the first {\it non ignored} node
2365 with empty status. [[realempty_1]] is identical to [[endempty_1]] if no
2366 ignored nodes appear at the empty end of the first partial child.
2368 PQNode<T,X,Y> *realempty_1 = 0;
2370 // Pointer to the second partial child.
2371 PQNode<T,X,Y> *partial_2 = 0;
2374 Pointer to the full endmost child (more
2375 precisely: to the endmost child appearing on the full side) of
2376 [[partial_2]]. In case that ignored nodes are used, this [[endfull_2]]
2377 may store the adress of an ignored node.
2379 PQNode<T,X,Y> *endfull_2 = 0;
2382 Pointer to the empty endmost child (more
2383 precisely: to the endmost child appearing on the empty side) of
2384 [[partial_2]]. In case that ignored nodes are used, this [[endempty_2]]
2385 may store the adress of an ignored node.
2387 PQNode<T,X,Y> *endempty_2 = 0;
2390 Pointer to the first {\it non ignored} node
2391 with empty status. [[realempty_2]] is identical to [[endempty_2]] if no
2392 ignored nodes appear at the empty end of the first partial child.
2394 PQNode<T,X,Y> *realempty_2 = 0;
2397 Pointer to a full sibling of
2398 [[partial_1]], if it exists. In case that ignored nodes are used
2399 this [[sibfull_1]] stores the direct sibling of [[partial_1]]
2400 on the side where the full siblings are. Hence [[sibfull_1]] may
2401 store an ignored node.
2403 PQNode<T,X,Y> *sibfull_1 = 0;
2406 Pointer to a partial sibling of
2407 [[partial_1]], if it exists. In case that ignored nodes are used
2408 this [[sibpartial_1]] stores the direct sibling of [[partial_1]]
2409 on the side where a partial sibling is. Hence [[sibpartial_1]] may
2410 store an ignored node.
2412 PQNode<T,X,Y> *sibpartial_1 = 0;
2415 Pointer to an empty sibling of
2416 [[parial_1]], if it exists. In case that ignored nodes are used
2417 this [[sibempty_1]] stores the direct sibling of [[partial_1]]
2418 on the side where the empty siblings are. Hence [[sibempty_1]] may
2419 store an ignored node.
2421 PQNode<T,X,Y> *sibempty_1 = 0;
2424 Pointer only used in case that [[partial_1]] has
2425 no non-ignored siblings on one side. [[partial_1]] then is endmost child
2426 of [[nodePtr]], but ignored children may appear between [[partial_1]]
2427 and the end of sequence of children of [[nodePtr]]. The
2428 [[nonstatussib_1]] then stores the adress of the endmost ignored child.
2429 Observe that it is not valid for a $Q$-node to have only one
2430 non-ignored child and several ignored children. Hence this situation
2431 is only allowed to appear {\bf once} on one side of [[partial_1]].
2432 Every other situation results in an error message.
2434 PQNode<T,X,Y> *nonstatussib_1 = 0;
2437 Pointer to a full sibling of
2438 [[partial_2]], if it exists. In case that ignored nodes are used
2439 this [[sibfull_2]] stores the direct sibling of [[partial_2]]
2440 on the side where the full siblings are. Hence [[sibfull_2]] may
2441 store an ignored node.
2443 PQNode<T,X,Y> *sibfull_2 = 0;
2446 Pointer to a partial sibling of
2447 [[partial_2]], if it exists. In case that ignored nodes are used
2448 this [[sibpartial_2]] stores the direct sibling of [[partial_2]]
2449 on the side where a partial sibling is. Hence [[sibpartial_2]] may
2450 store an ignored node.
2452 PQNode<T,X,Y> *sibpartial_2 = 0;
2455 Pointer to an empty sibling of
2456 [[parial_2]], if it exists. In case that ignored nodes are used
2457 this [[sibempty_2]] stores the direct sibling of [[partial_2]]
2458 on the side where the empty siblings are. Hence [[sibempty_2]] may
2459 store an ignored node.
2461 PQNode<T,X,Y> *sibempty_2 = 0;
2464 Pointer only used in case that [[partial_2]] has
2465 no non-ignored siblings on one side. [[partial_2]] then is endmost child
2466 of [[nodePtr]], but ignored children may appear between [[partial_2]]
2467 and the end of sequence of children of [[nodePtr]]. The
2468 [[nonstatussib_2]] then stores the adress of the endmost ignored child.
2469 Observe that it is not valid for a $Q$-node to have only one
2470 non-ignored child and several ignored children. Hence this situation
2471 is only allowed to appear {\bf once} on one side of [[partial_2]].
2472 Every other situation results in an error message.
2474 PQNode<T,X,Y> *nonstatussib_2 = 0;
2476 PQNode<T,X,Y> *helpptr = 0;
2478 PQNode<T,X,Y> *checkVarLeft = 0;
2480 PQNode<T,X,Y> *checkVarRight = 0;
2483 [[endmostcheck]] is [[1]], if [[partial_1]] is the endmost
2484 child of [[nodePtr]]. Per default, [[endmostcheck]] is [[0]].
2486 int endmostcheck = 0;
2489 nodePtr->status(PQNodeRoot::PARTIAL);
2490 if (!isRoot)
2491 nodePtr->m_parent->partialChildren->pushFront(nodePtr);
2493 if (!nodePtr->partialChildren->empty())
2494 // Get a partial child.
2496 partial_1 = nodePtr->partialChildren->popFrontRet();
2498 // Get the full and empty
2499 // endmost children of the
2500 // partial child [[partial_1]].
2501 checkVarLeft = clientLeftEndmost(partial_1);
2502 checkVarRight = clientRightEndmost(partial_1);
2503 if (checkVarLeft->status() == PQNodeRoot::FULL)
2505 endfull_1 = partial_1->m_leftEndmost;
2506 realfull_1 = checkVarLeft;
2508 else {
2509 // partial child with no full endmost child detected?
2510 OGDF_ASSERT(checkVarRight->status() == PQNodeRoot::FULL);
2512 endfull_1 = partial_1->m_rightEndmost;
2513 realfull_1 = checkVarRight;
2516 if (checkVarLeft->status() == PQNodeRoot::EMPTY)
2518 endempty_1 = partial_1->m_leftEndmost;
2519 realempty_1 = checkVarLeft;
2521 else {
2522 // partial child with no empty endmost child detected?
2523 OGDF_ASSERT(checkVarRight->status() == PQNodeRoot::EMPTY);
2525 endempty_1 = partial_1->m_rightEndmost;
2526 realempty_1 = checkVarRight;
2529 // Get the immediate
2530 // siblings of the partial
2531 // child [[partial_1]].
2532 if (clientSibLeft(partial_1) != 0)
2534 if (clientSibLeft(partial_1)->status() == PQNodeRoot::FULL)
2535 sibfull_1 = partial_1->m_sibLeft;
2536 else if (clientSibLeft(partial_1)->status() == PQNodeRoot::EMPTY)
2537 sibempty_1 = partial_1->m_sibLeft;
2538 else if (clientSibLeft(partial_1)->status() == PQNodeRoot::PARTIAL)
2539 sibpartial_1 = partial_1->m_sibLeft;
2541 else
2542 nonstatussib_1 = partial_1->m_sibLeft;
2544 if (clientSibRight(partial_1) != 0)
2546 if (clientSibRight(partial_1)->status() == PQNodeRoot::FULL)
2547 sibfull_1 = partial_1->m_sibRight;
2548 else if (clientSibRight(partial_1)->status() == PQNodeRoot::EMPTY)
2549 sibempty_1 = partial_1->m_sibRight;
2550 else if (clientSibRight(partial_1)->status() == PQNodeRoot::PARTIAL)
2551 sibpartial_1 = partial_1->m_sibRight;
2553 else {
2554 // partial child detected with no siblings of valid status?
2555 OGDF_ASSERT(nonstatussib_1 == 0);
2556 nonstatussib_1 = partial_1->m_sibRight;
2561 if (!nodePtr->partialChildren->empty())
2562 // There is a second partial child.
2564 partial_2 = nodePtr->partialChildren->popFrontRet();
2565 // Get the full and empty endmost
2566 // children of the partial
2567 // child [[partial_2]].
2569 checkVarLeft = clientLeftEndmost(partial_2);
2570 checkVarRight = clientRightEndmost(partial_2);
2571 if (checkVarLeft->status() == PQNodeRoot::FULL)
2573 endfull_2 = partial_2->m_leftEndmost;
2575 else {
2576 // partial child with no full endmost child detected?
2577 OGDF_ASSERT(checkVarRight->status() == PQNodeRoot::FULL);
2579 endfull_2 = partial_2->m_rightEndmost;
2582 if (checkVarLeft->status() == PQNodeRoot::EMPTY)
2584 endempty_2 = partial_2->m_leftEndmost;
2585 realempty_2 = checkVarLeft;
2587 else {
2588 // partial child with no empty endmost child detected?
2589 OGDF_ASSERT(checkVarRight->status() == PQNodeRoot::EMPTY);
2591 endempty_2 = partial_2->m_rightEndmost;
2592 realempty_2 = checkVarRight;
2594 // Get the immediate siblings
2595 // of the partial child
2596 // [[partial_2]].
2597 if (clientSibLeft(partial_2) != 0)
2599 if (clientSibLeft(partial_2)->status() == PQNodeRoot::FULL)
2600 sibfull_2 = partial_2->m_sibLeft;
2601 else if (clientSibLeft(partial_2)->status() == PQNodeRoot::EMPTY)
2602 sibempty_2 = partial_2->m_sibLeft;
2603 else if (clientSibLeft(partial_2)->status() == PQNodeRoot::PARTIAL)
2604 sibpartial_2 = partial_2->m_sibLeft;
2606 else
2607 nonstatussib_2 = partial_2->m_sibLeft;
2610 if (clientSibRight(partial_2) != 0)
2612 if (clientSibRight(partial_2)->status() == PQNodeRoot::FULL)
2613 sibfull_2 = partial_2->m_sibRight;
2614 else if (clientSibRight(partial_2)->status() == PQNodeRoot::EMPTY)
2615 sibempty_2 = partial_2->m_sibRight;
2616 else if (clientSibRight(partial_2)->status() == PQNodeRoot::PARTIAL)
2617 sibpartial_2 = partial_2->m_sibRight;
2619 else {
2620 OGDF_ASSERT(nonstatussib_2 == 0);
2621 nonstatussib_2 = partial_2->m_sibRight;
2626 if (partial_1 != 0 && partial_2 != 0)
2629 Connect the endmost
2630 children of the partial children [[partial_1]] and [[partial_2]] correctly
2631 with their new siblings. In doing this, all children of the partial
2632 children become children of [[nodePtr]]. The reader should observe that
2633 the parent pointers of the interior children of [[partial_1]] and
2634 [[partial_2]] are not updated in order to hit the linear time complexity.
2636 When including the children of the partial children to the children
2637 of [[nodePtr]], it is taken care that all full children
2638 form a consecutive sequence afterwards. If neccessary the pointers to the
2639 endmost children of [[nodePtr]] are updated.
2642 if (sibfull_1 != 0 && sibfull_2 != 0)
2643 // There are full children between
2644 // the 2 partial nodes.
2645 // Connect the full children
2646 // between the 2 partial children
2647 // with the full endmost children
2648 // of the 2 partial nodes.
2650 sibfull_1->changeSiblings(partial_1,endfull_1);
2651 endfull_1->putSibling(sibfull_1);
2652 sibfull_2->changeSiblings(partial_2,endfull_2);
2653 endfull_2->putSibling(sibfull_2);
2656 else if (sibpartial_1 != 0 && sibpartial_2 != 0)
2657 // There are no full children between
2658 // the 2 partial nodes. Connect the
2659 // full endmost children of the
2660 // partial nodes as siblings.
2662 if (partial_1 == sibpartial_2 && partial_2 == sibpartial_1)
2663 // Regular Case.
2665 endfull_1->putSibling(endfull_2);
2666 endfull_2->putSibling(endfull_1);
2668 // Only ignored children between
2669 // partial_1 and partial_2.
2670 else
2672 endfull_1->putSibling(sibpartial_1);
2673 sibpartial_1->changeSiblings(partial_1,endfull_1);
2674 endfull_2->putSibling(sibpartial_2);
2675 sibpartial_2->changeSiblings(partial_2,endfull_2);
2679 // Include the children of the
2680 // partial children with their
2681 // full nodes inbetween into
2682 // the sequence of the children of
2683 // Q-node nodePtr.
2684 if (sibempty_1 == 0)
2685 // partial_1 is endmost child of
2686 // nodePtr. Make the empty endmost
2687 // child of partial_1 be the new
2688 // endmost child of nodePtr.
2690 if (nonstatussib_1 == 0)
2691 // Regular case.
2693 nodePtr->changeEndmost(partial_1,endempty_1);
2695 else
2696 // Only ignored children between
2697 // partial_1 and one end of nodePtr.
2699 nonstatussib_1->changeSiblings(partial_1,endempty_1);
2700 endempty_1->putSibling(nonstatussib_1);
2702 endempty_1->m_parent = nodePtr;
2703 realempty_1->m_parent = nodePtr;
2706 else
2707 // partial_1 is not endmost child.
2709 sibempty_1->changeSiblings(partial_1,endempty_1);
2710 endempty_1->putSibling(sibempty_1);
2714 if (sibempty_2 == 0)
2715 // partial_2 is endmost child of
2716 // nodePtr. Make the empty endmost
2717 // child of partial_2 be the new
2718 // endmost child of nodePtr.
2720 if (nonstatussib_2 == 0)
2721 // Regular case.
2723 nodePtr->changeEndmost(partial_2,endempty_2);
2725 else
2726 // Only ignored children between
2727 // partial_1 and one end of
2728 // nodePtr.
2730 nonstatussib_2->changeSiblings(partial_2,endempty_2);
2731 endempty_2->putSibling(nonstatussib_2);
2733 endempty_2->m_parent = nodePtr;
2734 realempty_2->m_parent = nodePtr;
2737 else
2738 // partial_2 is not endmost child.
2740 sibempty_2->changeSiblings(partial_2,endempty_2);
2741 endempty_2->putSibling(sibempty_2);
2744 // Copy the full children of
2745 // partial_1 and partial_2 to
2746 // nodePtr.
2747 while (!partial_2->fullChildren->empty())
2749 helpptr = partial_2->fullChildren->popFrontRet();
2750 nodePtr->fullChildren->pushFront(helpptr);
2752 nodePtr->m_childCount = nodePtr->m_childCount +partial_2->m_childCount - 1;
2754 destroyNode(partial_2);
2756 while (!partial_1->fullChildren->empty())
2758 helpptr = partial_1->fullChildren->popFrontRet();
2759 nodePtr->fullChildren->pushFront(helpptr);
2761 nodePtr->m_childCount = nodePtr->m_childCount +partial_1->m_childCount - 1;
2763 destroyNode(partial_1);
2767 else if (partial_1 != 0)
2770 Connect the endmost
2771 children of the partial child [[partial_1]] correctly
2772 with their new siblings. In doing this, all children of the partial
2773 child become children of [[nodePtr]]. The reader should observe that
2774 the parent pointers of the interior children of [[partial_1]]
2775 are not updated in order to hit the linear time complexity.
2777 When including the children of [[partial_1]] to the children
2778 of [[nodePtr]], it is taken care that all full children
2779 form a consecutive sequence afterwards. If necessary the pointers to the
2780 endmost children of [[nodePtr]] are updated.
2784 if ((clientLeftEndmost(nodePtr) == partial_1) ||
2785 (clientRightEndmost(nodePtr) == partial_1))
2786 // partial_1 is endmost child.
2787 endmostcheck = 1;
2789 if (sibfull_1 != 0)
2790 // There are full children on one
2791 // side of the partial node.
2792 // Connect the full children with
2793 // the full endmost child of
2794 // partial_1.
2796 sibfull_1->changeSiblings(partial_1,endfull_1);
2797 endfull_1->putSibling(sibfull_1);
2800 else if (!endmostcheck)
2801 // There are not any full children
2802 // and partial_1 is not endmost.
2803 // So get the 2nd empty sibling
2804 // of partial_1 and connect it
2805 // to the full endmost child
2806 // of partial_1.
2808 if (partial_1->m_sibLeft != sibempty_1)
2809 sibempty_2 = partial_1->m_sibLeft;
2810 else
2811 sibempty_2 = partial_1->m_sibRight;
2813 sibempty_2->changeSiblings(partial_1,endfull_1);
2814 endfull_1->putSibling(sibempty_2);
2817 else
2818 // partial_1 is endmost child
2819 // and there are no full children.
2820 // Make the full endmost child of
2821 // partial_1 be the endmostchild
2822 // of nodePtr.
2825 if (nonstatussib_1 == 0)
2826 // Regular case.
2828 nodePtr->changeEndmost(partial_1,endfull_1);
2830 else
2831 // Only ignored children between
2832 // partial_1 and one end of
2833 // nodePtr.
2835 nonstatussib_1->changeSiblings(partial_1,endfull_1);
2836 endfull_1->putSibling(nonstatussib_1);
2838 endfull_1->m_parent = nodePtr;
2839 realfull_1->m_parent = nodePtr;
2843 if (sibempty_1 == 0)
2844 // There are no empty children.
2845 // partial_1 is endmost child of
2846 // nodePtr. Make the empty endmost
2847 // child of partial_1 be the new
2848 // endmost child of nodePtr.
2850 if (nonstatussib_1 == 0)
2851 // Regular case.
2853 nodePtr->changeEndmost(partial_1,endempty_1);
2855 else
2856 // Only ignored children between
2857 // partial_1 and one end of
2858 // nodePtr.
2860 nonstatussib_1->changeSiblings(partial_1,endempty_1);
2861 endempty_1->putSibling(nonstatussib_1);
2863 endempty_1->m_parent = nodePtr;
2864 realempty_1->m_parent = nodePtr;
2867 else
2868 // There are empty children. So
2869 // connect the empty endmost child
2870 // of partial_1 with sibempty_1.
2872 sibempty_1->changeSiblings(partial_1,endempty_1);
2873 endempty_1->putSibling(sibempty_1);
2876 while (!partial_1->fullChildren->empty())
2878 helpptr = partial_1->fullChildren->popFrontRet();
2879 nodePtr->fullChildren->pushFront(helpptr);
2882 nodePtr->m_childCount = nodePtr->m_childCount + partial_1->m_childCount - 1;
2883 destroyNode(partial_1);
2886 // else nodePtr does not have partial children. Then nothing is to do.
2890 /************************************************************************
2891 removeChildFromSiblings
2892 ************************************************************************/
2895 * The function removeChildFromSiblings() removes the node \a nodePtr from
2896 * the doubly linked list of its parent. In case that \a nodePtr is endmost
2897 * child of an Q-node or child of a P-node equiped with a valid
2898 * reference pointer \a referenceParent to its parent (see PQNode),
2899 * these pointers are considered as
2900 * well and the adjacent siblings of \a nodePtr have to cover
2901 * \a nodePtr's task.
2904 template<class T,class X,class Y>
2905 void PQTree<T,X,Y>::removeChildFromSiblings(PQNode<T,X,Y>* nodePtr)
2907 if (nodePtr->m_referenceParent != 0)
2910 Checksif [[nodePtr]] is connected with its parent via the reference
2911 pointers (see \ref{PQNode}). If so, the next sibling of [[nodePtr]]
2912 will be the the new reference child.
2914 nodePtr->m_referenceParent->m_referenceChild = nodePtr->m_sibRight;
2915 nodePtr->m_sibRight->m_referenceParent = nodePtr->m_referenceParent;
2916 if (nodePtr->m_referenceParent->m_referenceChild == nodePtr)
2917 nodePtr->m_referenceParent->m_referenceChild = 0;
2918 nodePtr->m_referenceParent = 0;
2920 else if (nodePtr->endmostChild())
2923 Check if [[nodePtr]] is the endmost child of a $Q$-node.
2924 If so, the next sibling of [[nodePtr]] will be the the new endmost
2925 child of the $Q$-node. Observe that the sibling then gets a valid
2926 pointer to its parent.
2928 PQNode<T,X,Y> *sibling = nodePtr->getNextSib(0);
2929 if (nodePtr->m_parent->m_leftEndmost == nodePtr)
2930 nodePtr->m_parent->m_leftEndmost = sibling;
2931 else if (nodePtr->m_parent->m_rightEndmost == nodePtr)
2932 nodePtr->m_parent->m_rightEndmost = sibling;
2933 if (sibling != 0)
2934 sibling->m_parent = nodePtr->m_parent;
2938 Remove [[nodePtr]] from its immediate siblings and links the
2939 siblings via the [[sibRight]] and [[sibLeft]] pointers.
2941 if ((nodePtr->m_sibRight != 0) && (nodePtr->m_sibRight != nodePtr))
2943 if (nodePtr->m_sibRight->m_sibLeft == nodePtr)
2944 nodePtr->m_sibRight->m_sibLeft = nodePtr->m_sibLeft;
2945 else {
2946 // Sibling was not connected to child?
2947 OGDF_ASSERT(nodePtr->m_sibRight->m_sibRight == nodePtr);
2948 nodePtr->m_sibRight->m_sibRight = nodePtr->m_sibLeft;
2951 if ((nodePtr->m_sibLeft != 0) && (nodePtr->m_sibLeft != nodePtr))
2953 if (nodePtr->m_sibLeft->m_sibRight == nodePtr)
2954 nodePtr->m_sibLeft->m_sibRight = nodePtr->m_sibRight;
2955 else {
2956 // Sibling was not connected to child?
2957 OGDF_ASSERT(nodePtr->m_sibLeft->m_sibLeft == nodePtr);
2958 nodePtr->m_sibLeft->m_sibLeft = nodePtr->m_sibRight;
2962 nodePtr->m_sibRight = 0;
2963 nodePtr->m_sibLeft = 0;
2967 /************************************************************************
2968 removeNodeFromTree
2969 ************************************************************************/
2972 * The function removeNodeFromTree() has to be handled with great care by
2973 * the user. This function is not used in any of the functions of
2974 * the class template PQTree and can only be accessed by inheritance.
2976 * Its objective is to remove a node \a child from the PQ-tree. To do so,
2977 * the \a parent of the node \a child has to be known by the user.
2978 * To indicate this, the parent has to be handed over by her.
2980 * <b>This function does not check if \a parent is the parent node of
2981 * \a child</b>. This has to be guaranteed by the user. The reason for
2982 * this riscfull approach lies in the details of the powerful data structure
2983 * PQ-tree. In order to reach linear runtime, the internal children
2984 * of a Q-node normally do not have valid parent pointers. So forcing
2985 * this function to search the parent would cost in worst case
2986 * linear runtime for one call of the function removeNodeFromTree().
2987 * Its up to the user to do better.
2989 * Calling removeNodeFromTree() with a 0-pointer for \a parent,
2990 * will always terminate this function with an ERROR-message and returning
2991 * -1 as value.
2993 * The return value is an integer value used to indicate how many children
2994 * the \a parent after the removal of \a child still has. The client should
2995 * observe that internal nodes in the PQ-tree which have just one or
2996 * no children at all do not make sense. However, the function
2997 * removeNodeFromTree() <b>does not check if \a parent has less than
2998 * two children after the removal of \< child</b>.
2999 * So in case that \a parent has less than two children, the user has to check
3000 * this by herself and remove the \a parent, probably using the function
3001 * checkIfOnlyChild().
3003 * There are two reasons why the function removeNodeFromTree() does
3004 * not check if \a parent has less than two children after the removal
3005 * of \a child:
3006 * -# The user might keep the node in the tree in order to add new nodes
3007 * as children to it.
3008 * -# Again, the parent of \a parent might not be known to \a parent,
3009 * hence removeNodeTree() would have to search, at the cost of linear time
3010 * consumption, for the parent of \a parent first before removing
3011 * \a parent from the tree.
3013 * Observe that removeNodeFromTree() does not free the allocated
3014 * memory of \a child. This has to be done by the user \b after calling
3015 * removeNodeFromTree(). It also offers the opportunity to reuse
3016 * deleted nodes. Observe that the identification number of a node
3017 * \a m_identificationNumber (see PQNode) cannot be changed.
3020 template<class T,class X,class Y>
3021 int PQTree<T,X,Y>::removeNodeFromTree(PQNode<T,X,Y>* parent,PQNode<T,X,Y>* child)
3023 if (parent !=0)
3025 removeChildFromSiblings(child);
3026 parent->m_childCount--;
3027 if ((child->status() == PQNodeRoot::FULL) || (child->status() == PQNodeRoot::PARTIAL))
3028 parent->m_pertChildCount--;
3029 return parent->m_childCount;
3031 else
3033 //parent is invalid 0-pointer.
3034 return -1;
3039 /************************************************************************
3040 sortExceptions
3041 ************************************************************************/
3044 * The function sortExceptions() is only called by the function frontExcept().
3045 * It sorts the exceptions before frontExcept()
3046 * scans the frontier.
3049 template<class T,class X,class Y>
3050 void PQTree<T,X,Y>::sortExceptions(int Exceptions[],int arraySize)
3052 bool changed = true;
3053 while (changed)
3055 changed = false;
3056 for (int i = 0; i < (arraySize-1); i++)
3058 if (Exceptions[i] > Exceptions[i+1])
3060 swap(Exceptions[i],Exceptions[i+1]);
3061 changed = true;
3068 /************************************************************************
3069 templateL1
3070 ************************************************************************/
3073 * The function templateL1() implements the template matching for
3074 * leaves.
3075 * The function requires as input any pointer to a node stored in
3076 * \a nodePtr. If the node stored in \a nodePtr is a PQLeaf,
3077 * templateL1() considers itself responsible for the node and will
3078 * apply the template matching for pertinent leaves to \a nodePtr.
3079 * If the flag \a isRoot is set to 1, it signalizes
3080 * templateL1() that \a nodePtr is the root of
3081 * the pertinent subtree. In any other case the flag has to be 0.
3083 * If templateL1() was responsible for \a nodePtr and the
3084 * reduction was successful, the return value is 1. Otherwise
3085 * the return value is 0.
3087 * The function updates the \a fullChildren stack of its parent, as long as
3088 * \a nodePtr is not the root of the pertinent subtree.
3089 * Observe that \a nodePtr needs a valid pointer to its parent. This
3090 * can be achieved by using the function Bubble() or any other
3091 * appropriate, user defined function.
3094 template<class T,class X,class Y>
3095 bool PQTree<T,X,Y>::templateL1(PQNode<T,X,Y> *nodePtr, bool isRoot)
3097 if ((nodePtr->type() == PQNodeRoot::leaf) && (nodePtr->status() == PQNodeRoot::FULL))
3099 if (!isRoot)
3100 nodePtr->m_parent->fullChildren->pushFront(nodePtr);
3101 return true;
3104 return false;
3108 /************************************************************************
3109 templateP1
3110 ************************************************************************/
3113 * The function templateP1() implements the template matching for
3114 * P-nodes with only full children.
3115 * The function requires as input any pointer to a node stored in
3116 * \a nodePtr. If the node stored in \a nodePtr is a P-node with
3117 * only full children,
3118 * templateP1() considers itself responsible for the node and will
3119 * apply the template matching for full P-nodes to \a nodePtr.
3120 * If the flag \a isRoot is set to 1, it signalizes
3121 * templateP1() that \a nodePtr is the root of
3122 * the pertinent subtree. In any other case the flag has to be 0.
3124 * If templateP1() was responsible for \a nodePtr and the
3125 * reduction was successful, the return value is 1. Otherwise
3126 * the return value is 0.
3128 * If the P-node is not the root of the pertinent subtree,
3129 * the \a fullChildren stack of the parent of \a nodePtr is updated.
3130 * If the P-node is the root of the pertinent subtree, nothing has to
3131 * be done.
3134 template<class T,class X,class Y>
3135 bool PQTree<T,X,Y>::templateP1(PQNode<T,X,Y> *nodePtr, bool isRoot)
3137 if (nodePtr->type() != PQNodeRoot::PNode ||
3138 nodePtr->fullChildren->size() != nodePtr->m_childCount)
3139 return false;
3140 else
3142 nodePtr->status(PQNodeRoot::FULL);
3143 if (!isRoot)
3144 nodePtr->m_parent->fullChildren->pushFront(nodePtr);
3146 return true;
3151 /************************************************************************
3152 templateP2
3153 ************************************************************************/
3156 * The function templateP2() implements the template matching for a
3157 * P-node with full \b and empty children that is the root of
3158 * the pertinent subtree.
3159 * The function requires as input any pointer to a node stored in
3160 * \ nodePtr. If the node stored in \a nodePtr is a P-node with
3161 * no partial children,
3162 * templateP2() considers itself responsible for the node and will
3163 * apply the template matching \b P2 to \a nodePtr.
3164 * Observe that the user calling this function has to make sure that
3165 * \a nodePtr is partial and is the root of the pertinent subtree.
3167 * If templateP2() was responsible for \a nodePtr and the
3168 * reduction was successful, the return value is 1. Otherwise
3169 * the return value is 0.
3171 * The function templateP2() creates a new full P-node that
3172 * will be the new root of the pertinent subtree. It then copies all full
3173 * children from \a nodePtr to the new root of the pertinent subtree.
3176 template<class T,class X,class Y>
3177 bool PQTree<T,X,Y>::templateP2(PQNode<T,X,Y> **nodePtr)
3179 if ((*nodePtr)->type() != PQNodeRoot::PNode ||
3180 (*nodePtr)->partialChildren->size() > 0)
3181 return false;
3183 (*nodePtr)->m_childCount =
3184 (*nodePtr)->m_childCount - (*nodePtr)->fullChildren->size() + 1;
3185 // Gather all full children of nodePtr
3186 // as children of the new P-node.
3187 // Delete them from nodePtr.
3189 PQNode<T,X,Y> *newNode = createNodeAndCopyFullChildren((*nodePtr)->fullChildren);
3190 // Correct parent-pointer and
3191 // sibling-pointers of the new P-node.
3193 newNode->m_parent = (*nodePtr);
3194 newNode->m_sibRight = (*nodePtr)->m_referenceChild->m_sibRight;
3195 newNode->m_sibLeft = newNode->m_sibRight->m_sibLeft;
3196 newNode->m_sibLeft->m_sibRight = newNode;
3197 newNode->m_sibRight->m_sibLeft = newNode;
3198 newNode->m_parentType = PQNodeRoot::PNode;
3199 // The new P-node now is the root of
3200 // the pertinent subtree.
3201 (*nodePtr) = newNode;
3203 return true;
3207 /************************************************************************
3208 templateP3
3209 ************************************************************************/
3212 * The function templateP3() implements the template matching for a
3213 * P-node with full \b and empty children that is \b not the root of
3214 * the pertinent subtree.
3215 * The function requires as input any pointer to a node stored in
3216 * \ nodePtr. If the node stored in \a nodePtr is a P-node with
3217 * no partial children,
3218 * templateP3() considers itself responsible for the node and will
3219 * apply the template matching \b P3 to \a nodePtr.
3220 * Observe that the user calling this function has to make sure that
3221 * \a nodePtr is partial and is not the root of the pertinent subtree.
3223 * If templateP3() was responsible for \a nodePtr and the
3224 * reduction was successful, the return value is 1. Otherwise
3225 * the return value is 0.
3227 * The function templateP3() creates
3228 * a new full P-node, stored in \a newPnode and copies the full children
3229 * of \a nodePtr to \a newPnode. \a nodePtr keeps all empty children
3230 * and will be labeled empty. A new partial Q-node will be created and stored
3231 * in \a newQnode. \a newQnode is placed at the position of \a nodePtr
3232 * in the tree and gets two children: \a nodePtr itself and the newly
3233 * created \a newPnode.
3235 * The function templateP3() uses a few variables.
3236 * - \a newPnode is the pointer to the new P-node, or, in case
3237 * that \a nodePtr has only one full child, is the pointer of this child.
3238 * - \a newQnode is the pointer to the new Q-node.
3239 * - \a newNode is used for the proper allocation of the new
3240 * Q-node.
3241 * - \a emptyNode is a pointer to any empty child of nodePtr.
3244 template<class T,class X,class Y>
3245 bool PQTree<T,X,Y>::templateP3(PQNode<T,X,Y> *nodePtr)
3247 if (nodePtr->type() != PQNodeRoot::PNode || nodePtr->partialChildren->size() > 0)
3248 return false;
3251 Create a new partial $Q$-node stored in [[newQnode]].
3252 It replaces [[nodePtr]] by the Q-node [[newQnode]] in the $PQ$-tree
3253 and makes [[nodePtr]] endmost child of [[newQnode]].
3254 This is done by updating parent-pointers and sibling-pointers.
3256 PQInternalNode<T,X,Y> *newNode = OGDF_NEW PQInternalNode<T,X,Y>(m_identificationNumber++,PQNodeRoot::QNode,PQNodeRoot::PARTIAL);
3257 PQNode<T,X,Y> *newQnode = newNode;
3258 m_pertinentNodes->pushFront(newQnode);
3260 exchangeNodes(nodePtr,newQnode);
3261 nodePtr->m_parent = newQnode;
3262 nodePtr->m_parentType = PQNodeRoot::QNode;
3264 newQnode->m_leftEndmost = (nodePtr);
3265 newQnode->m_childCount = 1;
3268 Create a new full $P$-node stored in [[newPnode]].
3269 It copies the full children of [[nodePtr]] to [[newPnode]].
3270 The new $P$-node will then be included into the tree as child of
3271 the new $Q$-node [[newQnode]].
3273 if (nodePtr->fullChildren->size() > 0)
3275 nodePtr->m_childCount = nodePtr->m_childCount -
3276 nodePtr->fullChildren->size();
3278 PQNode<T,X,Y> *newPnode = createNodeAndCopyFullChildren(nodePtr->fullChildren);
3279 newPnode->m_parentType = PQNodeRoot::QNode;
3281 // Update newQnode.
3282 newQnode->m_childCount++;
3283 newQnode->fullChildren->pushFront(newPnode);
3284 // Update sibling pointers.
3285 nodePtr->m_sibRight = newPnode;
3286 newPnode->m_sibLeft = nodePtr;
3287 newQnode->m_rightEndmost = newPnode;
3288 newPnode->m_parent = newQnode;
3291 // Check if nodePtr contains
3292 // only one son. If so, nodePtr
3293 // will be deleted from the tree.
3294 PQNode<T,X,Y> *emptyNode = nodePtr->m_referenceChild;
3295 checkIfOnlyChild(emptyNode,nodePtr);
3296 // Update partialchildren stack of
3297 // the parent of the new Q-node.
3298 newQnode->m_parent->partialChildren->pushFront(newQnode);
3300 return true;
3304 /************************************************************************
3305 templateP4
3306 ************************************************************************/
3309 * The function templateP4() implements the template matching for a
3310 * P-node with full, empty and exactly one partial children. The
3311 * P-node has to be the root of the pertinent subtree.
3312 * The function requires as input any pointer to a node stored in
3313 * \a nodePtr. If the node stored in \a nodePtr is a P-node with
3314 * one partial child,
3315 * templateP4() considers itself responsible for the node and will
3316 * apply the template matching \b P4 to \a nodePtr.
3317 * Observe that the user calling this function has to make sure that
3318 * \a nodePtr is the root of the pertinent subtree.
3320 * If templateP4() was responsible for \a nodePtr and the
3321 * reduction was successful, the return value is 1. Otherwise
3322 * the return value is 0.
3324 * The function templateP4() creates a new full P-node, if neccessary,
3325 * and copies the full children of \a nodePtr to this P-node.
3326 * The new P-node then is made endmost child of \a partialChild.
3327 * The node \a partialChild is used to store the adress of the partial
3328 * child of \a nodePtr.
3329 * The \a partialChild itself stays child of \a nodePtr.
3330 * Most of the here described action is done in the function
3331 * copyFullChildrenToPartial().
3334 template<class T,class X,class Y>
3335 bool PQTree<T,X,Y>::templateP4(PQNode<T,X,Y> **nodePtr)
3337 if ((*nodePtr)->type() != PQNodeRoot::PNode ||
3338 (*nodePtr)->partialChildren->size() != 1)
3339 return false;
3341 PQNode<T,X,Y> *partialChild = (*nodePtr)->partialChildren->popFrontRet();
3342 copyFullChildrenToPartial(*nodePtr,partialChild);
3343 // If nodePtr does not have any
3344 // empty children, then it has to
3345 // be deleted and the partial node
3346 // is occupying its place in the tree.
3347 checkIfOnlyChild(partialChild,*nodePtr);
3348 // The partial child now is
3349 // root of the pertinent subtree.
3350 *nodePtr = partialChild;
3352 return true;
3356 /************************************************************************
3357 templateP5
3358 ************************************************************************/
3361 * The function templateP5() implements the template matching for a
3362 * P-node with full, empty children and exactly one partial child. The
3363 * P-node is not allowed to be the root of the pertinent subtree.
3364 * The function requires as input any pointer to a node stored in
3365 * \a nodePtr. If the node stored in \a nodePtr is a P-node with
3366 * one partial child,
3367 * templateP5() considers itself responsible for the node and will
3368 * apply the template matching \b P5 to \a nodePtr.
3369 * Observe that the user calling this function has to make sure that
3370 * \a nodePtr is not the root of the pertinent subtree.
3372 * If templateP5() was responsible for \a nodePtr and the
3373 * reduction was successful, the return value is 1. Otherwise
3374 * the return value is 0.
3376 * The function templateP5() uses a few variables.
3377 * - \a partialChild is a pointer to the partial child of
3378 * \a nodePtr.
3379 * - \a checkNode is a pointer to the endmost empty child of
3380 * \a partialChild.
3381 * - \a emptyNode is a pointer to the empty node that is copied as
3382 * endmost child to \a partialChild.
3383 * - \a emptyChildCount stores the number of empty children of
3384 * \a nodePtr.
3386 * If neccessary, the function templateP5() creates a new full P-node
3387 * and copies all full children of \a nodePtr to this new full P-node.
3388 * All empty children of \a nodePtr stay empty children of \a nodePtr.
3390 * The new full P-node and \a nodePtr will be the new endmost children of
3391 * \a partialChild. The \a partialChild then occupies the position
3392 * of \a nodePtr in the PQ-tree.
3395 template<class T,class X,class Y>
3396 bool PQTree<T,X,Y>::templateP5(PQNode<T,X,Y> *nodePtr)
3398 if ((nodePtr->type() != PQNodeRoot::PNode) ||
3399 (nodePtr->partialChildren->size() != 1))
3400 return false;
3403 Remove [[partialChild]] from the children of [[nodePtr]]. The node
3404 [[partialChild]] then occupies the position of [[nodePtr]] in the
3405 $PQ$-tree which is done in the function call [[exchangeNodes]]
3406 (\ref{exchangeNodes}). The chunk then removes all full children from
3407 [[nodePtr]] and adds them as children of a new $P$-node as endmost
3408 child of [[partialChild]]. This is done in the function call
3409 [[copyFullChildrenToPartial]] (\ref{copyFullChildrenToPartial}).
3410 When this chunk has finished, [[nodePtr]] has only empty children.
3412 int emptyChildCount = nodePtr->m_childCount -
3413 nodePtr->fullChildren->size() - 1;
3414 PQNode<T,X,Y> *partialChild = nodePtr->partialChildren->popFrontRet();
3415 nodePtr->m_parent->partialChildren->pushFront(partialChild);
3416 removeChildFromSiblings(partialChild);
3417 exchangeNodes(nodePtr,partialChild);
3418 copyFullChildrenToPartial(nodePtr,partialChild);
3420 if (emptyChildCount > 0)
3423 Check if [[nodePtr]] has just one empty child. If so, the child
3424 is stored in [[emptyNode]] in order to be added to the empty
3425 side of the partial $Q$-node [[partialChild]]. If [[nodePtr]]
3426 has more than one empty child, [[nodePtr]] is stored in
3427 [[emptyNode]] in order to be added to the empty
3428 side of the partial $Q$-node [[partialChild]].
3430 PQNode<T,X,Y> *emptyNode;
3431 if (emptyChildCount == 1)
3433 emptyNode = nodePtr->m_referenceChild;
3434 removeChildFromSiblings(emptyNode);
3436 } else {
3437 emptyNode = nodePtr;
3438 emptyNode->m_childCount = emptyChildCount;
3442 Check at which side of [[partialChild]]
3443 the empty children hide. [[emptyNode]] stores the empty node
3444 that is added to the empty side of [[partialChild]].
3446 PQNode<T,X,Y> *checkNode;
3447 if (clientLeftEndmost(partialChild)->status() == PQNodeRoot::EMPTY)
3449 checkNode = partialChild->m_leftEndmost;
3450 partialChild->m_leftEndmost = emptyNode;
3452 else {
3453 // Endmostchild not found?
3454 OGDF_ASSERT(clientRightEndmost(partialChild)->status() == PQNodeRoot::EMPTY);
3456 checkNode = partialChild->m_rightEndmost;
3457 partialChild->m_rightEndmost = emptyNode;
3460 linkChildrenOfQnode(checkNode,emptyNode);
3461 emptyNode->m_parent = partialChild;
3462 emptyNode->m_parentType = PQNodeRoot::QNode;
3463 partialChild->m_childCount++;
3465 // If nodePtr did not have any empty
3466 // children it has to be deleted.
3467 if (emptyChildCount <= 1)
3468 destroyNode(nodePtr);
3470 return true;
3474 /************************************************************************
3475 templateP6
3476 ************************************************************************/
3479 * The function templateP6() implements the template matching for a
3480 * P-node with full, empty and exactly two partial children. The
3481 * P-node must be the root of the pertinent subtree.
3482 * The function requires as input any pointer to a node stored in
3483 * \a nodePtr. If the node stored in \a nodePtr is a P-node with
3484 * two partial children,
3485 * templateP6() considers itself responsible for the node and will
3486 * apply the template matching \b P6 to \a nodePtr.
3487 * Observe that the user calling this function has to make sure that
3488 * \a nodePtr is the root of the pertinent subtree.
3490 * If templateP6() was responsible for \a nodePtr and the
3491 * reduction was successful, the return value is 1. Otherwise
3492 * the return value is 0.
3494 * The function templateP6() creates, if neccessary,
3495 * a new full P-node and copies all the full children of \a nodePtr
3496 * to the new full P-node, whereas all empty children stay children of
3497 * \a nodePtr. The new P-node will be copied to one of the partial children
3498 * as endmost child of this partial node. The children of the second
3499 * partial node are copied to the first one, such that the pertinent nodes
3500 * form a consecutive sequence.
3502 * The following variables are used in the function templateP6().
3503 * - \a partial_1 is a pointer to the first partial child of
3504 * \a nodePtr.
3505 * - \a partial_2 is a pointer to the second partial child of
3506 * \a nodePtr.
3507 * - \a fullEnd_1 is a pointer to a full endmost child of \a partial_1.
3508 * - \a fullEnd_2 is a pointer to a full endmost child of \a partial_2.
3509 * - \a emptyEnd_2 is a pointer to the empty endmost child (more
3510 * precisely: to the endmost child appearing on the empty side) of
3511 * \a partial_2. In case that <em>ignored nodes</em> are used, this
3512 * \a emptyEnd_2 may store the adress of an ignored node.
3513 * - \a realEmptyEnd_2 is a pointer to the first <em>non ignored</em>
3514 * node with empty status on the empty side of \a partial_2. In case
3515 * that no ignored nodes are used, \a realEmpty_2 is identical to
3516 * \a endEmpty_2.
3519 template<class T,class X,class Y>
3520 bool PQTree<T,X,Y>::templateP6(PQNode<T,X,Y> **nodePtr)
3522 //PQNode<T,X,Y> *partial_1 = 0;
3523 //PQNode<T,X,Y> *partial_2 = 0;
3524 //PQNode<T,X,Y> *fullEnd_1 = 0;
3525 //PQNode<T,X,Y> *fullEnd_2 = 0;
3526 //PQNode<T,X,Y> *emptyEnd_2 = 0;
3527 //PQNode<T,X,Y> *realEmptyEnd_2 = 0;
3529 if ((*nodePtr)->type() != PQNodeRoot::PNode ||
3530 (*nodePtr)->partialChildren->size() != 2)
3531 return false;
3534 Get the partial children of [[nodePtr]] and removes the second
3535 partial child stored in [[partial_2]] from the children of
3536 [[nodePtr]]. If there are any full children of [[nodePtr]], the
3537 chunk removes them from the children of [[nodePtr]] and copies them
3538 as children to a new $P$-node. This new $P$-node is then made
3539 endmost child of [[partial_1]].
3541 PQNode<T,X,Y> *partial_1 = (*nodePtr)->partialChildren->popFrontRet();
3542 PQNode<T,X,Y> *partial_2 = (*nodePtr)->partialChildren->popFrontRet();
3544 removeChildFromSiblings(partial_2);
3545 (*nodePtr)->m_childCount--;
3546 copyFullChildrenToPartial(*nodePtr,partial_1);
3549 Check the endmost children of the two partial children of [[nodePtr]]
3550 and stores them at approriate places, remembering what kind of type
3551 the endmost children are.
3553 PQNode<T,X,Y> *fullEnd_1;
3554 if (clientLeftEndmost(partial_1)->status() == PQNodeRoot::FULL)
3555 fullEnd_1 = partial_1->m_leftEndmost;
3556 else {
3557 // partial child with no FULL endmost child detected?
3558 OGDF_ASSERT(clientRightEndmost(partial_1)->status() == PQNodeRoot::FULL);
3559 fullEnd_1 = partial_1->m_rightEndmost;
3562 PQNode<T,X,Y> *fullEnd_2 = 0;
3563 PQNode<T,X,Y> *emptyEnd_2 = 0;
3564 PQNode<T,X,Y> *realEmptyEnd_2 = 0;
3565 if (clientLeftEndmost(partial_2)->status() == PQNodeRoot::FULL)
3566 fullEnd_2 = partial_2->m_leftEndmost;
3567 else {
3568 // partial child with no FULL or EMPTY endmost child detected?
3569 OGDF_ASSERT(clientLeftEndmost(partial_2)->status() == PQNodeRoot::EMPTY);
3571 emptyEnd_2 = partial_2->m_leftEndmost;
3572 realEmptyEnd_2 = clientLeftEndmost(partial_2);
3575 if (clientRightEndmost(partial_2)->status() == PQNodeRoot::FULL)
3576 fullEnd_2 = partial_2->m_rightEndmost;
3577 else {
3578 // partial child with no FULL or EMPTY endmost child detected?
3579 OGDF_ASSERT(clientRightEndmost(partial_2)->status() == PQNodeRoot::EMPTY);
3581 emptyEnd_2 = partial_2->m_rightEndmost;
3582 realEmptyEnd_2 = clientRightEndmost(partial_2);
3585 OGDF_ASSERT(fullEnd_2 != emptyEnd_2)
3586 //partial child with same type of endmost child detected
3589 The children of [[partial_2]] are removed from their parent and
3590 added as children to [[partial_1]]. This is done by resetting the
3591 sibling pointers of the two endmost children of [[partial_1]] and
3592 [[partial_2]] and the endmost child pointers of [[partial_1]].
3593 Observe that the parent pointers are not updated. The node
3594 [[partial_2]] is deleted.
3596 while (!partial_2->fullChildren->empty())
3597 partial_1->fullChildren->pushFront(partial_2->fullChildren->popFrontRet());
3598 linkChildrenOfQnode(fullEnd_1,fullEnd_2);
3599 if (partial_1->m_leftEndmost == fullEnd_1)
3600 partial_1->m_leftEndmost = emptyEnd_2;
3601 else
3602 partial_1->m_rightEndmost = emptyEnd_2;
3604 emptyEnd_2->m_parent = partial_1;
3605 emptyEnd_2->m_parentType = PQNodeRoot::QNode;
3607 realEmptyEnd_2->m_parent = partial_1;
3608 realEmptyEnd_2->m_parentType = PQNodeRoot::QNode;
3610 partial_1->m_childCount = partial_1->m_childCount +
3611 partial_2->m_childCount;
3612 destroyNode(partial_2);
3616 // If nodePtr does not have any
3617 // empty children, then it has to
3618 // be deleted and the partial node
3619 // is occupying its place in the tree.
3620 checkIfOnlyChild(partial_1,*nodePtr);
3621 // partial_1 is now root of the
3622 // pertinent subtree.
3623 *nodePtr = partial_1;
3625 return true;
3629 /************************************************************************
3630 templateQ1
3631 ************************************************************************/
3634 * The function templateQ1() implements the template matching for
3635 * Q-nodes with only full children.
3636 * The function requires as input any pointer to a node stored in
3637 * \a nodePtr. If the node stored in \a nodePtr is a Q-node with
3638 * only full children,
3639 * templateQ1() considers itself responsible for the node and will
3640 * apply the template matching for full Q-nodes to \a nodePtr.
3641 * If the flag \a isRoot is set to 1, it signalizes
3642 * templateQ1() that \a nodePtr is the root of
3643 * the pertinent subtree. In any other case the flag has to be 0.
3645 * If templateQ1() was responsible for \a nodePtr and the
3646 * reduction was successful, the return value is 1. Otherwise
3647 * the return value is 0.
3649 * Different to the templateP1() for P-nodes,
3650 * this function is not able to check if Q-node is full by comparing
3651 * the number of children with the number of full children. The reason
3652 * is the application of the \a m_pseudoRoot at certain steps in the
3653 * matching algorithm. This \a m_pseudoRoot is used instead of the real
3654 * root of the pertinent subtree in case that no parent pointer was
3655 * found. But this implies that changing the number of the children of
3656 * the pertinent root is not registered by the pertinent root. Hence we
3657 * are not allowed to use the \a childCount of Q-nodes.
3660 template<class T,class X,class Y>
3661 bool PQTree<T,X,Y>::templateQ1(PQNode<T,X,Y> *nodePtr, bool isRoot)
3663 if (nodePtr->type() == PQNodeRoot::QNode &&
3664 nodePtr != m_pseudoRoot &&
3665 clientLeftEndmost(nodePtr)->status() == PQNodeRoot::FULL &&
3666 clientRightEndmost(nodePtr)->status() == PQNodeRoot::FULL)
3668 PQNode<T,X,Y>* seqStart = 0;
3669 PQNode<T,X,Y>* seqEnd = 0;
3670 if (checkChain(nodePtr,clientLeftEndmost(nodePtr),&seqStart,&seqEnd))
3672 nodePtr->status(PQNodeRoot::FULL);
3673 if (!isRoot)
3674 nodePtr->m_parent->fullChildren->pushFront(nodePtr);
3675 return true;
3679 return false;
3683 /************************************************************************
3684 templateQ2
3685 ************************************************************************/
3688 * The function templateQ2() implements the template matching for
3689 * Q-nodes with a pertinent
3690 * sequence of children on one side of the Q-node.
3691 * The function requires as input any pointer to a node stored in
3692 * \a nodePtr. If the node stored in \a nodePtr is a Q-node with
3693 * a pertinent
3694 * sequence of children on one side of the Q-node,
3695 * templateQ2() considers itself responsible for the node and will
3696 * apply the template matching \b Q2 to \a nodePtr.
3697 * If the flag \a isRoot is set to 1, it signalizes
3698 * templateQ2() that \a nodePtr is the root of
3699 * the pertinent subtree. In any other case the flag has to be 0.
3701 * If templateQ2() was responsible for \a nodePtr and the
3702 * reduction was successful, the return value is 1. Otherwise
3703 * the return value is 0.
3705 * Below a short description is given of all different cases that
3706 * may occure and that are handled by the function templateQ2(), \b regardless
3707 * whether the Q-node \a nodePtr is root of the pertinent subtree or not.
3708 * The description is somewhat trunkated and should be understood as a
3709 * stenographic description of the labels of the children of \a nodePtr
3710 * when running through the children from one side to the other. Of course
3711 * we leave the mirror-images out.
3712 * - full, empty
3713 * - full, partial, empty
3714 * - full, partial
3715 * - partial, empty.
3717 * templateQ2() uses the following variables.
3718 * - \a fullNode is a pointer to the full endmost child of \a nodePtr.
3719 * - \a sequenceBegin is a pointer to the first node of the
3720 * sequence of full children. Identical to the node fullNode and
3721 * mainly needed by the function checkChain().
3722 * - \a sequenceEnd is a pointer to the last node of the sequence
3723 * of full children. Is set by the function checkChain().
3724 * - \a partialChild is a pointer to the partial child of \a nodePtr.
3725 * - \a sequenceCons is 1 if all full children of
3726 * \a nodePtr form a consecutive sequence with one full child beeing
3727 * an endmost child of \a nodePtr \b and the partial child is
3728 * adjacent to the sequence.
3730 * templateQ2() first checks if one of the above mentioned cases
3731 * occures and
3732 * then applies the necessary template matching.
3733 * No special action has to be performed for the full nodes. If there exists
3734 * a partial child that will be stored in \a partialChild, its children
3735 * are made children of \a nodePtr. So to say, \a partialChild is lifted
3736 * up to the Q-node \a nodePtr and the occurance of the children
3737 * of \a partialChild is fixed within the children of \a nodePtr.
3738 * (Remember that a partial child is also a Q-node).
3741 template<class T,class X,class Y>
3742 bool PQTree<T,X,Y>::templateQ2(PQNode<T,X,Y> *nodePtr,bool isRoot)
3744 if (nodePtr->type() != PQNodeRoot::QNode ||
3745 nodePtr->partialChildren->size() > 1)
3746 return false;
3748 bool sequenceCons = false;
3749 if (nodePtr->fullChildren->size() > 0)
3752 Get a full endmost child of
3753 the $Q$-node [[nodePtr]] if there exists one.
3755 PQNode<T,X,Y> *fullNode = 0;
3756 if (nodePtr->m_leftEndmost != 0)
3758 fullNode = clientLeftEndmost(nodePtr);
3759 if (fullNode->status() != PQNodeRoot::FULL)
3760 fullNode = 0;
3762 if (nodePtr->m_rightEndmost != 0 && fullNode == 0)
3764 fullNode = clientRightEndmost(nodePtr);
3765 if (fullNode->status() != PQNodeRoot::FULL)
3766 fullNode = 0;
3770 In case that a full endmost child of [[nodePtr]] exists, this
3771 child has been stored in [[fullNode]] and the chunk checks by
3772 calling the function [[checkChain]] (\ref{checkChain}), if all
3773 full children of [[nodePtr]] form a consecutive sequence.
3774 In case that the full children
3775 of [[nodePtr]] form a consecutive sequence the
3776 return value of [[checkChain]] is [[1]]. If a partial child
3777 stored in [[partialChild]] exists, the chunk checks if
3778 [[partialChild]] is adjacent to the sequence of full children.
3779 If the latter case is [[1]], the flag [[sequenceCons]] is
3780 set to [[1]] and the function [[templateQ2]] is allowed to
3781 reduce the pertient children of [[nodePtr]].
3783 PQNode<T,X,Y> *sequenceBegin = 0;
3784 PQNode<T,X,Y> *sequenceEnd = 0;
3785 if (fullNode != 0)
3786 sequenceCons = checkChain(nodePtr,fullNode,&sequenceBegin,&sequenceEnd);
3788 if (sequenceCons && (nodePtr->partialChildren->size() == 1))
3790 PQNode<T,X,Y> *partialChild = nodePtr->partialChildren->front();
3791 sequenceCons = false;
3793 if (clientSibLeft(sequenceEnd) == partialChild ||
3794 clientSibRight(sequenceEnd) == partialChild)
3795 sequenceCons = true;
3798 else
3800 if (!nodePtr->partialChildren->empty())
3803 If the $Q$-node [[nodePtr]] has no full children but one
3804 partial child this chunk checks, if the partial child is
3805 endmost child of the [[nodePtr]]. If this is not the case,
3806 [[nodePtr]] cannot be reduced by the template matching
3807 {\bf Q2}.
3809 //nodePtr->partialChildren->startAtBottom();
3810 //partialChild = nodePtr->partialChildren->readNext();
3811 PQNode<T,X,Y> *partialChild = nodePtr->partialChildren->front();
3812 if ((clientLeftEndmost(nodePtr) == partialChild) ||
3813 (clientRightEndmost(nodePtr) == partialChild))
3814 sequenceCons = true;
3818 if (sequenceCons)
3819 removeBlock(nodePtr,isRoot);
3821 return sequenceCons;
3825 /************************************************************************
3826 templateQ3
3827 ************************************************************************/
3830 * The function templateQ3() implements the template matching for
3831 * Q-nodes with empty and/or partial children at both ends and a sequence
3832 * of full and/or partial children in the middle. The Q-node must be the
3833 * root of the pertinent subtree.
3834 * The function requires as input any pointer to a node stored in
3835 * \a nodePtr. If the node stored in \a nodePtr is a Q-node
3836 * with empty and/or partial children at both ends and a sequence
3837 * full or partial children in the middle,
3838 * templateQ3() considers itself responsible for the node and will
3839 * apply the template matching \b Q3 to \a nodePtr.
3840 * Observe that the user calling this function has to make sure that
3841 * \a nodePtr is the root of the pertinent subtree.
3843 * If templateQ3() was responsible for \a nodePtr and the
3844 * reduction was successful, the return value is 1. Otherwise
3845 * the return value is 0.
3847 * Below a short description is given of all different cases that
3848 * may occure and are handled by the function templateQ3(), \b regardless
3849 * whether the Q-node \a nodePtr is the root of the pertinent subtree or not.
3850 * The description is somewhat trunkated and should be understood as a
3851 * stenographic description of the labels of the children of \a nodePtr
3852 * when running through the children from one side to the other. Of course
3853 * we leave the mirror-images out.
3854 * - empty, full, empty
3855 * - empty, partial, full, partial, empty
3856 * - empty, partial, full, empty
3857 * - empty, partial, full, partial
3858 * - partial, full, partial
3859 * - empty, partial, partial, empty
3860 * - empty, partial, partial
3861 * - partial, partial
3863 * The function templateQ3() uses the following variables.
3864 * - \a fullChild is a pointer to an arbitrary full child of \a nodePtr.
3865 * - \a fullStart is a pointer to the first full child of a
3866 * consecutive sequence of full children.
3867 * - \a fullEnd is a pointer to the last full child of a
3868 * consecutive sequence of full children.
3869 * - \a partial_1 is a pointer to the first partial child of \a nodePtr.
3870 * - \a partial_2 is a pointer to the second partial child of \a nodePtr.
3871 * - \a conssequence is 1 if the pertinent children of
3872 * \a nodePtr form a consecutive sequence with at most one partial
3873 * child at every end of the sequence.
3874 * - \a found is a help variable.
3876 * templateQ3() first checks if one of the above mentioned cases
3877 * occures and then applies the neccessary template matching.
3878 * No special action has to be performed for the full nodes. If there exist
3879 * one or two partial children which will be stored in \a partial_1
3880 * or \a partial_2, their children
3881 * are made children of \a nodePtr. So to say, \a partial_1 and
3882 * partial_2 are lifted up to the Q-node \a nodePtr
3883 * and the occurance of their children
3884 * is fixed within the children of \a nodePtr.
3887 template<class T,class X,class Y>
3888 bool PQTree<T,X,Y>::templateQ3(PQNode<T,X,Y> *nodePtr)
3890 if (nodePtr->type() != PQNodeRoot::QNode || nodePtr->partialChildren->size() >= 3)
3891 return false;
3893 bool conssequence = false;
3894 bool found = false;
3897 Check ifthe
3898 pertinent children of [[nodePtr]] form a consecutive sequence. We
3899 differ between two cases:
3900 \begin{enumerate}
3901 \item There exist full children of [[nodePtr]]. First check with
3902 the function [[checkChain]] (\ref{checkChain}) if the full children
3903 form a consecutive sequence. In case that the check was
3904 successful, check if each partial child is adjacent to a full child.
3905 If both checks were successful, the pertient children form a
3906 consecutive sequence.
3907 \item There do not exist full children. Check if the partial
3908 children (there are at most two of them) form a consecutive sequence.
3909 If the test was successful, the pertinent children form a
3910 consecutive sequence.
3913 if (!nodePtr->fullChildren->empty())
3916 A consecutive
3917 sequence of full children has been detected, containing all full
3918 children of [[nodePtr]]. The chunk checks if each partial child
3919 of [[nodePtr]] is adjacent to a full child. Observe that the
3920 function [[templateQ3]] only reaches this chunk when [[nodePtr]]
3921 has less than three partial children.
3923 PQNode<T,X,Y> *fullChild = nodePtr->fullChildren->front();
3924 PQNode<T,X,Y> *fullStart = 0;
3925 PQNode<T,X,Y> *fullEnd = 0;
3926 conssequence = checkChain(nodePtr,fullChild,&fullStart,&fullEnd);
3927 if (conssequence)
3929 ListIterator<PQNode<T,X,Y>*> it;
3930 for (it = nodePtr->partialChildren->begin(); it.valid(); ++it)
3932 PQNode<T,X,Y> *partial_1 = *it;
3933 found = false;
3934 if ((clientSibLeft(fullStart) == partial_1) ||
3935 (clientSibRight(fullStart) == partial_1) ||
3936 (clientSibLeft(fullEnd) == partial_1) ||
3937 (clientSibRight(fullEnd) == partial_1) )
3938 found = true;
3939 if (!found)
3940 conssequence = found;
3945 else if (nodePtr->partialChildren->size() == 2)
3948 In case that the node [[nodePtr]] does not have any full children,
3949 this chunk checks if the partial children are adjacent.
3951 PQNode<T,X,Y> *partial_1 = nodePtr->partialChildren->front();
3952 PQNode<T,X,Y> *partial_2 = nodePtr->partialChildren->back();
3953 if ((clientSibLeft(partial_1) == partial_2) ||
3954 (clientSibRight(partial_1) == partial_2) )
3955 found = true;
3956 conssequence = found;
3959 if (conssequence)
3960 removeBlock(nodePtr,true);
3962 return conssequence;
3968 #endif