Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

Loading...
Searching...
No Matches
PCNode.h
Go to the documentation of this file.
1
32#pragma once
33
34#include <ogdf/basic/basic.h>
35#include <ogdf/basic/memory.h>
39
40#include <array>
41#include <cstddef>
42#include <iosfwd>
43#include <new>
44#include <utility>
45#include <vector>
46
47namespace ogdf::pc_tree {
48class PCTree;
49struct PCNodeChildrenIterable;
50struct PCNodeNeighborsIterable;
51
62class OGDF_EXPORT PCNode : public IntrusiveList<PCNode>::node {
63 friend OGDF_EXPORT std::ostream&(operator<<)(std::ostream&, const ogdf::pc_tree::PCTree*);
64 friend OGDF_EXPORT std::ostream&(operator<<)(std::ostream&, const ogdf::pc_tree::PCNode*);
65
66 friend class PCTree;
67 friend class PCTreeForest;
70
71public:
75 struct TempInfo {
76 PCNode *predPartial = nullptr, *nextPartial = nullptr;
77 PCNode* tpPred = nullptr;
78 PCNode* tpPartialPred = nullptr;
79 size_t tpPartialHeight = 0;
80 PCNode* tpSucc = nullptr;
81 std::vector<PCNode*> fullNeighbors;
82 PCNode *ebEnd1 = nullptr, *fbEnd1 = nullptr, *fbEnd2 = nullptr, *ebEnd2 = nullptr;
83
84 void replaceNeighbor(PCNode* oldNeigh, PCNode* newNeigh) {
85 if (tpPred == oldNeigh) {
86 tpPred = newNeigh;
87 }
88 if (tpPartialPred == oldNeigh) {
89 tpPartialPred = newNeigh;
90 }
91 if (tpSucc == oldNeigh) {
92 tpSucc = newNeigh;
93 }
94 if (ebEnd1 == oldNeigh) {
95 ebEnd1 = newNeigh;
96 }
97 if (ebEnd2 == oldNeigh) {
98 ebEnd2 = newNeigh;
99 }
100 if (fbEnd1 == oldNeigh) {
101 fbEnd1 = newNeigh;
102 }
103 if (fbEnd2 == oldNeigh) {
104 fbEnd2 = newNeigh;
105 }
106 }
107
108 void clear() {
109 nextPartial = predPartial = nullptr;
110 tpPred = tpPartialPred = tpSucc = nullptr;
111 ebEnd1 = fbEnd1 = fbEnd2 = ebEnd2 = nullptr;
112 tpPartialHeight = 0;
113 fullNeighbors.clear();
114 }
115 };
116
117 using LeafUserData = std::array<void*, sizeof(TempInfo) / sizeof(void*)>;
118
119private:
120 // index in registry
121 size_t m_id;
122
123 // global
125
126 // private
129 PCNode* m_parentPNode = nullptr;
130 mutable UnionFindIndex m_parentCNodeId = UNIONFINDINDEX_EMPTY;
131 PCNode* m_sibling1 = nullptr;
132 PCNode* m_sibling2 = nullptr;
133 PCNode* m_child1 = nullptr;
134 PCNode* m_child2 = nullptr;
135 size_t m_childCount = 0;
136 mutable NodeLabel m_label = NodeLabel::Unknown;
137 mutable size_t m_timestamp = 0;
138
139 // leaves need no temp info, so they can easily store user data
140 union {
143 };
144
146 : IntrusiveList<PCNode>::node(), m_id(id), m_forest(forest), m_nodeType(nodeType) {
147 if (nodeType == PCNodeType::Leaf) {
148 new (&m_userData) LeafUserData;
149 } else {
150 new (&m_temp) TempInfo;
151 }
152 }
153
155 if (m_nodeType == PCNodeType::Leaf) {
156 m_userData.~array();
157 } else {
158 m_temp.~TempInfo();
159 }
160 }
161
162public:
168
172 void appendChild(PCNode* child, bool begin = false);
173
177 void insertBetween(PCNode* sib1, PCNode* sib2);
178
182 void detach();
183
187 void replaceWith(PCNode* repl);
188
193
197 void flip() { std::swap(m_child1, m_child2); }
198
199private:
203 void replaceSibling(PCNode* oldS, PCNode* newS);
204
208 void rotateChildOutside(bool child1 = true);
209
213 void replaceOuterChild(PCNode* oldC, PCNode* newC);
214
218 void setParent(PCNode* parent);
219
224
228 void changeType(PCNodeType newType) {
229 if (m_nodeType == PCNodeType::Leaf && newType != PCNodeType::Leaf) {
230 m_userData.~array();
231 new (&m_temp) TempInfo;
232 } else if (m_nodeType != PCNodeType::Leaf && newType == PCNodeType::Leaf) {
233 m_temp.~TempInfo();
234 new (&m_userData) LeafUserData;
235 }
236 m_nodeType = newType;
237 }
238
240
241public:
247
251 PCNode* getNextSibling(const PCNode* pred) const;
252
256 PCNode* getOtherOuterChild(const PCNode* child) const;
257
262 PCNode* getNextNeighbor(const PCNode* pred, const PCNode* curr) const;
263
267 void proceedToNextNeighbor(PCNode*& pred, PCNode*& curr) const;
268
273
278
283
285
286public:
292
296 bool isDetached() const {
297 if (m_parentCNodeId == UNIONFINDINDEX_EMPTY && m_parentPNode == nullptr) {
298 return true;
299 } else {
300 OGDF_ASSERT(m_parentCNodeId == UNIONFINDINDEX_EMPTY || m_parentPNode == nullptr);
301 return false;
302 }
303 }
304
308 bool isValidNode(const PCTreeForest* ofForest = nullptr) const;
309
310 bool isLeaf() const { return m_nodeType == PCNodeType::Leaf; }
311
315 bool isParentOf(const PCNode* other) const {
316 OGDF_ASSERT(other != nullptr);
317 OGDF_ASSERT(m_forest == other->m_forest);
318 return other->getParent() == this;
319 }
320
324 bool isSiblingOf(const PCNode* other) const {
325 OGDF_ASSERT(other != nullptr);
326 OGDF_ASSERT(m_forest == other->m_forest);
327 return this->getParent() == other->getParent();
328 }
329
333 bool isSiblingAdjacent(const PCNode* sibling) const {
334 OGDF_ASSERT(isSiblingOf(sibling));
335 OGDF_ASSERT(this != sibling);
336 return m_sibling1 == sibling || m_sibling2 == sibling;
337 }
338
343 bool areNeighborsAdjacent(const PCNode* neigh1, const PCNode* neigh2) const;
344
348 bool isChildOuter(const PCNode* child) const {
349 OGDF_ASSERT(isParentOf(child));
350 return m_child1 == child || m_child2 == child;
351 }
352
356 bool isOuterChild() const { return m_sibling1 == nullptr || m_sibling2 == nullptr; }
357
359
360public:
366
367 const TempInfo& constTempInfo() const {
368 checkTimestamp();
369 OGDF_ASSERT(!isLeaf());
370 return m_temp;
371 }
372
373 bool isFull() const { return getLabel() == NodeLabel::Full; }
374
376 // this operation does not reset the temp info
377 return m_forest->m_timestamp == m_timestamp ? m_label : NodeLabel::Empty;
378 }
379
381 checkTimestamp();
382 m_label = l;
383 }
384
385private:
386 // these methods are slightly faster if we already called checkTimestamp()
388 OGDF_ASSERT(m_forest->m_timestamp == m_timestamp);
389 return m_label;
390 }
391
393 OGDF_ASSERT(m_forest->m_timestamp == m_timestamp);
394 m_label = l;
395 }
396
397public:
402 OGDF_ASSERT(isLeaf());
403 return m_userData;
404 }
405
409 const LeafUserData& leafUserData() const {
410 OGDF_ASSERT(isLeaf());
411 return m_userData;
412 }
413
414private:
415 void checkTimestamp() const;
416
418 checkTimestamp();
419 OGDF_ASSERT(!isLeaf());
420 return m_temp;
421 }
422
423 size_t addFullNeighbor(PCNode* fullNeigh) {
424 checkTimestamp();
425 OGDF_ASSERT(!isLeaf());
426 OGDF_ASSERT(fullNeigh->isFull());
427 m_temp.fullNeighbors.push_back(fullNeigh);
428 return m_temp.fullNeighbors.size();
429 }
430
432 checkTimestamp();
433 OGDF_ASSERT(!isLeaf());
434 OGDF_ASSERT(nonFullNeigh != nullptr);
435 if (nonFullNeigh == m_temp.ebEnd1) {
436 OGDF_ASSERT(areNeighborsAdjacent(m_temp.ebEnd1, m_temp.fbEnd1));
437 return m_temp.fbEnd1;
438 } else {
439 OGDF_ASSERT(nonFullNeigh == m_temp.ebEnd2);
440 OGDF_ASSERT(areNeighborsAdjacent(m_temp.ebEnd2, m_temp.fbEnd2));
441 return m_temp.fbEnd2;
442 }
443 }
444
446
447public:
452 size_t index() const { return m_id; }
453
454 PCNodeType getNodeType() const { return m_nodeType; }
455
456 size_t getChildCount() const { return m_childCount; }
457
458 size_t getDegree() const { return isDetached() ? m_childCount : m_childCount + 1; }
459
460 PCNode* getChild1() const { return m_child1; }
461
462 PCNode* getChild2() const { return m_child2; }
463
468 OGDF_ASSERT(m_childCount == 1);
469 return m_child1;
470 }
471
472 PCNode* getSibling1() const { return m_sibling1; }
473
474 PCNode* getSibling2() const { return m_sibling2; }
475
476 PCTreeForest* getForest() const { return m_forest; }
477
479
481};
482
487}
An intrusive list for the leaves of a PCTree.
Predeclaration of various PC-tree related classes and enums.
PCTreeForests contain multiple PCTrees that can be merged with each other.
Basic declarations, included by all source files.
Class for the representation of nodes.
Definition Graph_d.h:241
A node in a PC-tree that is either a P-node, C-node or leaf.
Definition PCNode.h:62
PCNode(PCTreeForest *forest, size_t id, PCNodeType nodeType)
Definition PCNode.h:145
void rotateChildOutside(bool child1=true)
Make this node an outer child of its parent.
size_t index() const
Definition PCNode.h:452
void checkTimestamp() const
void mergeIntoParent()
Merges this C-node into its C-node parent.
bool isLeaf() const
Definition PCNode.h:310
bool areNeighborsAdjacent(const PCNode *neigh1, const PCNode *neigh2) const
PCNode *& getFullNeighInsertionPoint(PCNode *nonFullNeigh)
Definition PCNode.h:431
void replaceOuterChild(PCNode *oldC, PCNode *newC)
Notify this node that one of its outer children was replaced.
PCNodeNeighborsIterable neighbors(PCNode *first=nullptr)
void setLabel(NodeLabel l)
Definition PCNode.h:380
PCTreeForest * getForest() const
Definition PCNode.h:476
bool isValidNode(const PCTreeForest *ofForest=nullptr) const
Perform multiple debug checks and return true if getForest == ofForest.
size_t getDegree() const
Definition PCNode.h:458
bool isSiblingAdjacent(const PCNode *sibling) const
Definition PCNode.h:333
PCNodeType m_nodeType
Definition PCNode.h:128
void flip()
Reverse the stored order of children.
Definition PCNode.h:197
void replaceSibling(PCNode *oldS, PCNode *newS)
Notify this node that one of its adjacent siblings changed.
PCNode * getOnlyChild() const
Check whether this node has only one child and return it.
Definition PCNode.h:467
bool isSiblingOf(const PCNode *other) const
Definition PCNode.h:324
bool isFull() const
Definition PCNode.h:373
void detach()
Detach this node from its parent.
LeafUserData & leafUserData()
Definition PCNode.h:401
LeafUserData m_userData
Definition PCNode.h:142
void setLabelUnchecked(NodeLabel l)
Definition PCNode.h:392
void forceDetach()
detach() without performing checks.
void setParent(PCNode *parent)
Notify this node that it has a new parent.
PCNode * getOtherOuterChild(const PCNode *child) const
Given one outer child, return the outer child on the other side.
friend std::ostream & operator<<)(std::ostream &, const ogdf::pc_tree::PCNode *)
const LeafUserData & leafUserData() const
Definition PCNode.h:409
const TempInfo & constTempInfo() const
Definition PCNode.h:367
void appendChild(PCNode *child, bool begin=false)
Append a (detached) child node to the begin or end of this nodes' children.
PCNode * getParent() const
friend std::ostream & operator<<)(std::ostream &, const ogdf::pc_tree::PCTree *)
PCNode * getChild1() const
Definition PCNode.h:460
PCNode * getNextSibling(const PCNode *pred) const
Given the left or right sibling pred, return the adjacent sibling on the other side.
void changeType(PCNodeType newType)
Overwrite the type of this node without updating any other data structures.
Definition PCNode.h:228
bool isOuterChild() const
Definition PCNode.h:356
PCNodeChildrenIterable children()
PCTreeForest * m_forest
Definition PCNode.h:124
bool isChildOuter(const PCNode *child) const
Definition PCNode.h:348
NodeLabel getLabel() const
Definition PCNode.h:375
PCNode * getChild2() const
Definition PCNode.h:462
PCNode * getSibling1() const
Definition PCNode.h:472
NodeLabel getLabelUnchecked() const
Definition PCNode.h:387
PCNode * getNextNeighbor(const PCNode *pred, const PCNode *curr) const
Method to walk the cyclic order of all neighbors, i.e., all children plus the parent,...
std::array< void *, sizeof(TempInfo)/sizeof(void *)> LeafUserData
Definition PCNode.h:117
bool isParentOf(const PCNode *other) const
Definition PCNode.h:315
TempInfo & tempInfo()
Definition PCNode.h:417
bool isDetached() const
Definition PCNode.h:296
void proceedToNextNeighbor(PCNode *&pred, PCNode *&curr) const
Iteration-convenience version of getNextNeighbor() that updates the variables pred to curr and curr t...
size_t getChildCount() const
Definition PCNode.h:456
void replaceWith(PCNode *repl)
Swaps this node inplace with a (detached) other one.
void insertBetween(PCNode *sib1, PCNode *sib2)
Insert a (detached) child node directly between two adjacent children of this node.
PCNodeType getNodeType() const
Definition PCNode.h:454
PCNode * getSibling2() const
Definition PCNode.h:474
size_t addFullNeighbor(PCNode *fullNeigh)
Definition PCNode.h:423
Multiple PCTrees can be created within the same PCTreeForest, which allows merging the trees later on...
A PC-tree represents a set of cyclic orders of its leaves by labeling its inner nodes as either P- or...
Definition PCTree.h:118
#define OGDF_EXPORT
Specifies that a function or class is exported by the OGDF dynamic library (shared object / DLL),...
Definition config.h:117
NodeElement * node
The type of nodes.
Definition Graph_d.h:71
#define OGDF_ASSERT(expr)
Assert condition expr. See doc/build.md for more information.
Definition basic.h:52
#define OGDF_NEW_DELETE
Makes the class use OGDF's memory allocator.
Definition memory.h:85
Declaration of memory manager for allocating small pieces of memory.
void proceedToNextSibling(PCNode *&pred, PCNode *&curr)
Iteration-convenience version of PCNode::getNextSibling() that updates the variables pred to curr and...
size_t UnionFindIndex
const UnionFindIndex UNIONFINDINDEX_EMPTY
long long nodeType
Temporary information used during each step of the PCTree::makeConsecutive() update operation.
Definition PCNode.h:75
void replaceNeighbor(PCNode *oldNeigh, PCNode *newNeigh)
Definition PCNode.h:84
std::vector< PCNode * > fullNeighbors
Definition PCNode.h:81