Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

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 <list>
42 #include <vector>
43 
44 namespace ogdf::pc_tree {
45 struct OGDF_EXPORT PCNodeChildrenIterable;
46 struct OGDF_EXPORT PCNodeNeighborsIterable;
47 
58 class OGDF_EXPORT PCNode : public IntrusiveList<PCNode>::node {
59  friend OGDF_EXPORT std::ostream&(operator<<)(std::ostream&, const ogdf::pc_tree::PCTree*);
60  friend OGDF_EXPORT std::ostream&(operator<<)(std::ostream&, const ogdf::pc_tree::PCNode*);
61 
62  friend class PCTree;
63  friend class PCTreeForest;
64  friend struct PCNodeChildrenIterable;
65  friend struct PCNodeNeighborsIterable;
66 
67 public:
71  struct TempInfo {
72  PCNode *predPartial = nullptr, *nextPartial = nullptr;
73  PCNode* tpPred = nullptr;
74  PCNode* tpPartialPred = nullptr;
75  size_t tpPartialHeight = 0;
76  PCNode* tpSucc = nullptr;
77  std::vector<PCNode*> fullNeighbors;
78  PCNode *ebEnd1 = nullptr, *fbEnd1 = nullptr, *fbEnd2 = nullptr, *ebEnd2 = nullptr;
79 
80  void replaceNeighbor(PCNode* oldNeigh, PCNode* newNeigh) {
81  if (tpPred == oldNeigh) {
82  tpPred = newNeigh;
83  }
84  if (tpPartialPred == oldNeigh) {
85  tpPartialPred = newNeigh;
86  }
87  if (tpSucc == oldNeigh) {
88  tpSucc = newNeigh;
89  }
90  if (ebEnd1 == oldNeigh) {
91  ebEnd1 = newNeigh;
92  }
93  if (ebEnd2 == oldNeigh) {
94  ebEnd2 = newNeigh;
95  }
96  if (fbEnd1 == oldNeigh) {
97  fbEnd1 = newNeigh;
98  }
99  if (fbEnd2 == oldNeigh) {
100  fbEnd2 = newNeigh;
101  }
102  }
103 
104  void clear() {
105  nextPartial = predPartial = nullptr;
106  tpPred = tpPartialPred = tpSucc = nullptr;
107  ebEnd1 = fbEnd1 = fbEnd2 = ebEnd2 = nullptr;
108  tpPartialHeight = 0;
109  fullNeighbors.clear();
110  }
111  };
112 
113  using LeafUserData = std::array<void*, sizeof(TempInfo) / sizeof(void*)>;
114 
115 private:
116  // index in registry
117  size_t m_id;
118 
119  // global
121 
122  // private
125  PCNode* m_parentPNode = nullptr;
126  mutable UnionFindIndex m_parentCNodeId = UNIONFINDINDEX_EMPTY;
127  PCNode* m_sibling1 = nullptr;
128  PCNode* m_sibling2 = nullptr;
129  PCNode* m_child1 = nullptr;
130  PCNode* m_child2 = nullptr;
131  size_t m_childCount = 0;
132  mutable NodeLabel m_label = NodeLabel::Unknown;
133  mutable size_t m_timestamp = 0;
134 
135  // leaves need no temp info, so they can easily store user data
136  union {
137  mutable TempInfo m_temp;
139  };
140 
141  PCNode(PCTreeForest* forest, size_t id, PCNodeType nodeType)
142  : IntrusiveList<PCNode>::node(), m_id(id), m_forest(forest), m_nodeType(nodeType) {
143  if (nodeType == PCNodeType::Leaf) {
144  new (&m_userData) LeafUserData;
145  } else {
146  new (&m_temp) TempInfo;
147  }
148  }
149 
151  if (m_nodeType == PCNodeType::Leaf) {
152  m_userData.~array();
153  } else {
154  m_temp.~TempInfo();
155  }
156  }
157 
158 public:
163 
168  void appendChild(PCNode* child, bool begin = false);
169 
173  void insertBetween(PCNode* sib1, PCNode* sib2);
174 
178  void detach();
179 
183  void replaceWith(PCNode* repl);
184 
188  void mergeIntoParent();
189 
193  void flip() { std::swap(m_child1, m_child2); }
194 
195 private:
199  void replaceSibling(PCNode* oldS, PCNode* newS);
200 
204  void rotateChildOutside(bool child1 = true);
205 
209  void replaceOuterChild(PCNode* oldC, PCNode* newC);
210 
214  void setParent(PCNode* parent);
215 
219  void forceDetach();
220 
224  void changeType(PCNodeType newType) {
225  if (m_nodeType == PCNodeType::Leaf && newType != PCNodeType::Leaf) {
226  m_userData.~array();
227  new (&m_temp) TempInfo;
228  } else if (m_nodeType != PCNodeType::Leaf && newType == PCNodeType::Leaf) {
229  m_temp.~TempInfo();
230  new (&m_userData) LeafUserData;
231  }
232  m_nodeType = newType;
233  }
234 
236 
237 public:
242 
247  PCNode* getNextSibling(const PCNode* pred) const;
248 
252  PCNode* getOtherOuterChild(const PCNode* child) const;
253 
258  PCNode* getNextNeighbor(const PCNode* pred, const PCNode* curr) const;
259 
263  void proceedToNextNeighbor(PCNode*& pred, PCNode*& curr) const;
264 
268  PCNode* getParent() const;
269 
273  PCNodeChildrenIterable children();
274 
278  PCNodeNeighborsIterable neighbors(PCNode* first = nullptr);
279 
281 
282 public:
287 
292  bool isDetached() const {
293  if (m_parentCNodeId == UNIONFINDINDEX_EMPTY && m_parentPNode == nullptr) {
294  return true;
295  } else {
296  OGDF_ASSERT(m_parentCNodeId == UNIONFINDINDEX_EMPTY || m_parentPNode == nullptr);
297  return false;
298  }
299  }
300 
304  bool isValidNode(const PCTreeForest* ofForest = nullptr) const;
305 
306  bool isLeaf() const { return m_nodeType == PCNodeType::Leaf; }
307 
311  bool isParentOf(const PCNode* other) const {
312  OGDF_ASSERT(other != nullptr);
313  OGDF_ASSERT(m_forest == other->m_forest);
314  return other->getParent() == this;
315  }
316 
320  bool isSiblingOf(const PCNode* other) const {
321  OGDF_ASSERT(other != nullptr);
322  OGDF_ASSERT(m_forest == other->m_forest);
323  return this->getParent() == other->getParent();
324  }
325 
329  bool isSiblingAdjacent(const PCNode* sibling) const {
330  OGDF_ASSERT(isSiblingOf(sibling));
331  OGDF_ASSERT(this != sibling);
332  return m_sibling1 == sibling || m_sibling2 == sibling;
333  }
334 
339  bool areNeighborsAdjacent(const PCNode* neigh1, const PCNode* neigh2) const;
340 
344  bool isChildOuter(const PCNode* child) const {
345  OGDF_ASSERT(isParentOf(child));
346  return m_child1 == child || m_child2 == child;
347  }
348 
352  bool isOuterChild() const { return m_sibling1 == nullptr || m_sibling2 == nullptr; }
353 
355 
356 public:
361 
363  const TempInfo& constTempInfo() const {
364  checkTimestamp();
365  OGDF_ASSERT(!isLeaf());
366  return m_temp;
367  }
368 
369  bool isFull() const { return getLabel() == NodeLabel::Full; }
370 
371  NodeLabel getLabel() const {
372  // this operation does not reset the temp info
373  return m_forest->m_timestamp == m_timestamp ? m_label : NodeLabel::Empty;
374  }
375 
376  void setLabel(NodeLabel l) {
377  checkTimestamp();
378  m_label = l;
379  }
380 
381 private:
382  // these methods are slightly faster if we already called checkTimestamp()
383  inline NodeLabel getLabelUnchecked() const {
384  OGDF_ASSERT(m_forest->m_timestamp == m_timestamp);
385  return m_label;
386  }
387 
388  inline void setLabelUnchecked(NodeLabel l) {
389  OGDF_ASSERT(m_forest->m_timestamp == m_timestamp);
390  m_label = l;
391  }
392 
393 public:
398  OGDF_ASSERT(isLeaf());
399  return m_userData;
400  }
401 
405  const LeafUserData& leafUserData() const {
406  OGDF_ASSERT(isLeaf());
407  return m_userData;
408  }
409 
410 private:
411  void checkTimestamp() const;
412 
414  checkTimestamp();
415  OGDF_ASSERT(!isLeaf());
416  return m_temp;
417  }
418 
419  size_t addFullNeighbor(PCNode* fullNeigh) {
420  checkTimestamp();
421  OGDF_ASSERT(!isLeaf());
422  OGDF_ASSERT(fullNeigh->isFull());
423  m_temp.fullNeighbors.push_back(fullNeigh);
424  return m_temp.fullNeighbors.size();
425  }
426 
428  checkTimestamp();
429  OGDF_ASSERT(!isLeaf());
430  OGDF_ASSERT(nonFullNeigh != nullptr);
431  if (nonFullNeigh == m_temp.ebEnd1) {
432  OGDF_ASSERT(areNeighborsAdjacent(m_temp.ebEnd1, m_temp.fbEnd1));
433  return m_temp.fbEnd1;
434  } else {
435  OGDF_ASSERT(nonFullNeigh == m_temp.ebEnd2);
436  OGDF_ASSERT(areNeighborsAdjacent(m_temp.ebEnd2, m_temp.fbEnd2));
437  return m_temp.fbEnd2;
438  }
439  }
440 
442 
443 public:
447  size_t index() const { return m_id; }
449 
450  PCNodeType getNodeType() const { return m_nodeType; }
451 
452  size_t getChildCount() const { return m_childCount; }
453 
454  size_t getDegree() const { return isDetached() ? m_childCount : m_childCount + 1; }
455 
456  PCNode* getChild1() const { return m_child1; }
457 
458  PCNode* getChild2() const { return m_child2; }
459 
463  PCNode* getOnlyChild() const {
464  OGDF_ASSERT(m_childCount == 1);
465  return m_child1;
466  }
467 
468  PCNode* getSibling1() const { return m_sibling1; }
469 
470  PCNode* getSibling2() const { return m_sibling2; }
471 
472  PCTreeForest* getForest() const { return m_forest; }
473 
475 
477 };
478 
482 OGDF_EXPORT void proceedToNextSibling(PCNode*& pred, PCNode*& curr);
483 }
ogdf::pc_tree::PCNode::tempInfo
TempInfo & tempInfo()
Definition: PCNode.h:413
ogdf::pc_tree::PCNode::leafUserData
LeafUserData & leafUserData()
Definition: PCNode.h:397
ogdf::pc_tree::PCNode::isOuterChild
bool isOuterChild() const
Definition: PCNode.h:352
ogdf::pc_tree::PCNode::m_forest
PCTreeForest * m_forest
Definition: PCNode.h:120
ogdf::pc_tree::PCNode::m_userData
LeafUserData m_userData
Definition: PCNode.h:138
OGDF_ASSERT
#define OGDF_ASSERT(expr)
Assert condition expr. See doc/build.md for more information.
Definition: basic.h:54
ogdf::pc_tree::PCNodeNeighborsIterable
Definition: PCTreeIterators.h:94
ogdf::pc_tree::PCNode::isParentOf
bool isParentOf(const PCNode *other) const
Definition: PCNode.h:311
ogdf::begin
HypergraphRegistry< HypernodeElement >::iterator begin(const HypergraphRegistry< HypernodeElement > &self)
ogdf::pc_tree::NodeLabel::Empty
@ Empty
ogdf::pc_tree
Definition: NodePCRotation.h:37
ogdf::pc_tree::PCTree
A PC-tree represents a set of cyclic orders of its leaves by labeling its inner nodes as either P- or...
Definition: PCTree.h:109
ogdf::pc_tree::PCNode::getChild1
PCNode * getChild1() const
Definition: PCNode.h:456
ogdf::pc_tree::PCNodeChildrenIterable
Definition: PCTreeIterators.h:82
IntrusiveList.h
An intrusive list for the leaves of a PCTree. TODO should be moved to a central location; merge with ...
ogdf::pc_tree::PCNode::changeType
void changeType(PCNodeType newType)
Overwrite the type of this node without updating any other data structures.
Definition: PCNode.h:224
ogdf::pc_tree::PCNode::TempInfo
Temporary information used during each step of the PCTree::makeConsecutive() update operation.
Definition: PCNode.h:71
ogdf::nodeType
long long nodeType
Definition: NodeTypePatterns.h:44
ogdf::pc_tree::PCNode::isSiblingAdjacent
bool isSiblingAdjacent(const PCNode *sibling) const
Definition: PCNode.h:329
ogdf::pc_tree::PCNode::isSiblingOf
bool isSiblingOf(const PCNode *other) const
Definition: PCNode.h:320
ogdf::pc_tree::PCNode::isChildOuter
bool isChildOuter(const PCNode *child) const
Definition: PCNode.h:344
ogdf::pc_tree::PCNode::isFull
bool isFull() const
Definition: PCNode.h:369
ogdf::pc_tree::PCNode::getNodeType
PCNodeType getNodeType() const
Definition: PCNode.h:450
ogdf::pc_tree::PCNode::isLeaf
bool isLeaf() const
Definition: PCNode.h:306
ogdf::pc_tree::PCNode::leafUserData
const LeafUserData & leafUserData() const
Definition: PCNode.h:405
OGDF_NEW_DELETE
#define OGDF_NEW_DELETE
Makes the class use OGDF's memory allocator.
Definition: memory.h:84
ogdf::pc_tree::PCNode::m_nodeType
PCNodeType m_nodeType
Definition: PCNode.h:124
ogdf::pc_tree::PCNodeType
PCNodeType
Definition: PCEnum.h:42
ogdf::pc_tree::proceedToNextSibling
void proceedToNextSibling(PCNode *&pred, PCNode *&curr)
Iteration-convenience version of PCNode::getNextSibling() that updates the variables pred to curr and...
ogdf::pc_tree::PCNode::PCNode
PCNode(PCTreeForest *forest, size_t id, PCNodeType nodeType)
Definition: PCNode.h:141
ogdf::pc_tree::PCNode::getParent
PCNode * getParent() const
ogdf::pc_tree::PCNode::constTempInfo
const TempInfo & constTempInfo() const
Definition: PCNode.h:363
ogdf::pc_tree::PCNode::getChild2
PCNode * getChild2() const
Definition: PCNode.h:458
ogdf::pc_tree::PCNode::getChildCount
size_t getChildCount() const
Definition: PCNode.h:452
ogdf::pc_tree::PCNode::setLabel
void setLabel(NodeLabel l)
Definition: PCNode.h:376
ogdf::pc_tree::IntrusiveList
Definition: IntrusiveList.h:41
ogdf::pc_tree::NodeLabel
NodeLabel
Definition: PCEnum.h:40
ogdf::pc_tree::PCNode::getLabelUnchecked
NodeLabel getLabelUnchecked() const
Definition: PCNode.h:383
ogdf::pc_tree::PCTreeForest
Multiple PCTrees can be created within the same PCTreeForest, which allows merging the trees later on...
Definition: PCTreeForest.h:53
ogdf::pc_tree::PCNode::getOnlyChild
PCNode * getOnlyChild() const
Check whether this node has only one child and return it.
Definition: PCNode.h:463
ogdf::pc_tree::NodeLabel::Full
@ Full
ogdf::pc_tree::PCNode::addFullNeighbor
size_t addFullNeighbor(PCNode *fullNeigh)
Definition: PCNode.h:419
ogdf::pc_tree::PCNode::getLabel
NodeLabel getLabel() const
Definition: PCNode.h:371
ogdf::pc_tree::PCNode::TempInfo::fullNeighbors
std::vector< PCNode * > fullNeighbors
Definition: PCNode.h:77
ogdf::pc_tree::PCNode::getDegree
size_t getDegree() const
Definition: PCNode.h:454
ogdf::pc_tree::UNIONFINDINDEX_EMPTY
const UnionFindIndex UNIONFINDINDEX_EMPTY
Definition: PCTreeForest.h:46
ogdf::pc_tree::UnionFindIndex
size_t UnionFindIndex
Definition: PCTreeForest.h:44
ogdf::pc_tree::PCNode::TempInfo::replaceNeighbor
void replaceNeighbor(PCNode *oldNeigh, PCNode *newNeigh)
Definition: PCNode.h:80
ogdf::pc_tree::PCNode::getForest
PCTreeForest * getForest() const
Definition: PCNode.h:472
ogdf::pc_tree::PCNode::getFullNeighInsertionPoint
PCNode *& getFullNeighInsertionPoint(PCNode *nonFullNeigh)
Definition: PCNode.h:427
ogdf::pc_tree::PCNode::m_id
size_t m_id
Definition: PCNode.h:117
ogdf::pc_tree::PCNode::setLabelUnchecked
void setLabelUnchecked(NodeLabel l)
Definition: PCNode.h:388
PCEnum.h
Predeclaration of various PC-tree related classes and enums.
ogdf::pc_tree::PCNode::getSibling2
PCNode * getSibling2() const
Definition: PCNode.h:470
ogdf::pc_tree::PCTreeForest::m_timestamp
size_t m_timestamp
Definition: PCTreeForest.h:63
ogdf::pc_tree::PCNode
A node in a PC-tree that is either a P-node, C-node or leaf.
Definition: PCNode.h:58
basic.h
Basic declarations, included by all source files.
ogdf::pc_tree::NodeLabel::Unknown
@ Unknown
OGDF_EXPORT
#define OGDF_EXPORT
Specifies that a function or class is exported by the OGDF DLL.
Definition: config.h:101
ogdf::pc_tree::PCNode::getSibling1
PCNode * getSibling1() const
Definition: PCNode.h:468
PCTreeForest.h
PCTreeForests contain multiple PCTrees that can be merged with each other.
ogdf::pc_tree::PCNode::TempInfo::clear
void clear()
Definition: PCNode.h:104
ogdf::pc_tree::PCNode::m_temp
TempInfo m_temp
Definition: PCNode.h:137
ogdf::pc_tree::PCNode::LeafUserData
std::array< void *, sizeof(TempInfo)/sizeof(void *)> LeafUserData
Definition: PCNode.h:113
ogdf::NodeElement
Class for the representation of nodes.
Definition: Graph_d.h:233
ogdf::pc_tree::PCNode::~PCNode
~PCNode()
Definition: PCNode.h:150
memory.h
Declaration of memory manager for allocating small pieces of memory.
ogdf::pc_tree::PCNodeType::Leaf
@ Leaf
ogdf::pc_tree::PCNode::isDetached
bool isDetached() const
Definition: PCNode.h:292
ogdf::pc_tree::PCNode::flip
void flip()
Reverse the stored order of children.
Definition: PCNode.h:193