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 <cstddef>
42 #include <iosfwd>
43 #include <new>
44 #include <utility>
45 #include <vector>
46 
47 namespace ogdf::pc_tree {
48 class PCTree;
49 struct OGDF_EXPORT PCNodeChildrenIterable;
50 struct OGDF_EXPORT PCNodeNeighborsIterable;
51 
62 class 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;
68  friend struct PCNodeChildrenIterable;
69  friend struct PCNodeNeighborsIterable;
70 
71 public:
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 
119 private:
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 {
141  mutable TempInfo m_temp;
143  };
144 
145  PCNode(PCTreeForest* forest, size_t id, PCNodeType nodeType)
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 
162 public:
167 
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 
192  void mergeIntoParent();
193 
197  void flip() { std::swap(m_child1, m_child2); }
198 
199 private:
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 
223  void forceDetach();
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 
241 public:
246 
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 
272  PCNode* getParent() const;
273 
277  PCNodeChildrenIterable children();
278 
282  PCNodeNeighborsIterable neighbors(PCNode* first = nullptr);
283 
285 
286 public:
291 
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 
360 public:
365 
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 
375  NodeLabel getLabel() const {
376  // this operation does not reset the temp info
377  return m_forest->m_timestamp == m_timestamp ? m_label : NodeLabel::Empty;
378  }
379 
380  void setLabel(NodeLabel l) {
381  checkTimestamp();
382  m_label = l;
383  }
384 
385 private:
386  // these methods are slightly faster if we already called checkTimestamp()
387  inline NodeLabel getLabelUnchecked() const {
388  OGDF_ASSERT(m_forest->m_timestamp == m_timestamp);
389  return m_label;
390  }
391 
392  inline void setLabelUnchecked(NodeLabel l) {
393  OGDF_ASSERT(m_forest->m_timestamp == m_timestamp);
394  m_label = l;
395  }
396 
397 public:
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 
414 private:
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 
447 public:
451  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 
467  PCNode* getOnlyChild() const {
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 
486 OGDF_EXPORT void proceedToNextSibling(PCNode*& pred, PCNode*& curr);
487 }
ogdf::pc_tree::PCNode::tempInfo
TempInfo & tempInfo()
Definition: PCNode.h:417
ogdf::pc_tree::PCNode::leafUserData
LeafUserData & leafUserData()
Definition: PCNode.h:401
ogdf::pc_tree::PCNode::isOuterChild
bool isOuterChild() const
Definition: PCNode.h:356
ogdf::pc_tree::PCNode::m_forest
PCTreeForest * m_forest
Definition: PCNode.h:124
ogdf::pc_tree::PCNode::m_userData
LeafUserData m_userData
Definition: PCNode.h:142
OGDF_ASSERT
#define OGDF_ASSERT(expr)
Assert condition expr. See doc/build.md for more information.
Definition: basic.h:66
ogdf::pc_tree::PCNodeNeighborsIterable
Definition: PCTreeIterators.h:103
ogdf::pc_tree::PCNode::isParentOf
bool isParentOf(const PCNode *other) const
Definition: PCNode.h:315
ogdf::begin
HypergraphRegistry< HypernodeElement >::iterator begin(const HypergraphRegistry< HypernodeElement > &self)
ogdf::pc_tree::NodeLabel::Empty
@ Empty
ogdf::pc_tree
Definition: NodePCRotation.h:47
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:118
ogdf::pc_tree::PCNode::getChild1
PCNode * getChild1() const
Definition: PCNode.h:460
ogdf::pc_tree::PCNodeChildrenIterable
Definition: PCTreeIterators.h:91
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:228
ogdf::pc_tree::PCNode::TempInfo
Temporary information used during each step of the PCTree::makeConsecutive() update operation.
Definition: PCNode.h:75
ogdf::nodeType
long long nodeType
Definition: NodeTypePatterns.h:44
ogdf::pc_tree::PCNode::isSiblingAdjacent
bool isSiblingAdjacent(const PCNode *sibling) const
Definition: PCNode.h:333
ogdf::pc_tree::PCNode::isSiblingOf
bool isSiblingOf(const PCNode *other) const
Definition: PCNode.h:324
ogdf::pc_tree::PCNode::isChildOuter
bool isChildOuter(const PCNode *child) const
Definition: PCNode.h:348
ogdf::pc_tree::PCNode::isFull
bool isFull() const
Definition: PCNode.h:373
ogdf::pc_tree::PCNode::getNodeType
PCNodeType getNodeType() const
Definition: PCNode.h:454
ogdf::pc_tree::PCNode::isLeaf
bool isLeaf() const
Definition: PCNode.h:310
ogdf::pc_tree::PCNode::leafUserData
const LeafUserData & leafUserData() const
Definition: PCNode.h:409
OGDF_NEW_DELETE
#define OGDF_NEW_DELETE
Makes the class use OGDF's memory allocator.
Definition: memory.h:85
ogdf::pc_tree::PCNode::m_nodeType
PCNodeType m_nodeType
Definition: PCNode.h:128
ogdf::pc_tree::PCNodeType
PCNodeType
Definition: PCEnum.h:43
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:145
ogdf::pc_tree::PCNode::getParent
PCNode * getParent() const
ogdf::pc_tree::PCNode::constTempInfo
const TempInfo & constTempInfo() const
Definition: PCNode.h:367
ogdf::pc_tree::PCNode::getChild2
PCNode * getChild2() const
Definition: PCNode.h:462
ogdf::pc_tree::PCNode::getChildCount
size_t getChildCount() const
Definition: PCNode.h:456
ogdf::pc_tree::PCNode::setLabel
void setLabel(NodeLabel l)
Definition: PCNode.h:380
ogdf::pc_tree::IntrusiveList
Definition: IntrusiveList.h:42
ogdf::pc_tree::NodeLabel
NodeLabel
Definition: PCEnum.h:41
ogdf::pc_tree::PCNode::getLabelUnchecked
NodeLabel getLabelUnchecked() const
Definition: PCNode.h:387
ogdf::pc_tree::PCTreeForest
Multiple PCTrees can be created within the same PCTreeForest, which allows merging the trees later on...
Definition: PCTreeForest.h:59
ogdf::pc_tree::PCNode::getOnlyChild
PCNode * getOnlyChild() const
Check whether this node has only one child and return it.
Definition: PCNode.h:467
ogdf::pc_tree::NodeLabel::Full
@ Full
ogdf::pc_tree::PCNode::addFullNeighbor
size_t addFullNeighbor(PCNode *fullNeigh)
Definition: PCNode.h:423
ogdf::pc_tree::PCNode::getLabel
NodeLabel getLabel() const
Definition: PCNode.h:375
ogdf::pc_tree::PCNode::TempInfo::fullNeighbors
std::vector< PCNode * > fullNeighbors
Definition: PCNode.h:81
ogdf::pc_tree::PCNode::getDegree
size_t getDegree() const
Definition: PCNode.h:458
ogdf::pc_tree::UNIONFINDINDEX_EMPTY
const UnionFindIndex UNIONFINDINDEX_EMPTY
Definition: PCTreeForest.h:52
ogdf::pc_tree::UnionFindIndex
size_t UnionFindIndex
Definition: PCTreeForest.h:50
ogdf::pc_tree::PCNode::TempInfo::replaceNeighbor
void replaceNeighbor(PCNode *oldNeigh, PCNode *newNeigh)
Definition: PCNode.h:84
ogdf::pc_tree::PCNode::getForest
PCTreeForest * getForest() const
Definition: PCNode.h:476
ogdf::pc_tree::PCNode::getFullNeighInsertionPoint
PCNode *& getFullNeighInsertionPoint(PCNode *nonFullNeigh)
Definition: PCNode.h:431
ogdf::pc_tree::PCNode::m_id
size_t m_id
Definition: PCNode.h:121
ogdf::pc_tree::PCNode::setLabelUnchecked
void setLabelUnchecked(NodeLabel l)
Definition: PCNode.h:392
PCEnum.h
Predeclaration of various PC-tree related classes and enums.
ogdf::pc_tree::PCNode::getSibling2
PCNode * getSibling2() const
Definition: PCNode.h:474
ogdf::pc_tree::PCTreeForest::m_timestamp
size_t m_timestamp
Definition: PCTreeForest.h:69
ogdf::pc_tree::PCNode
A node in a PC-tree that is either a P-node, C-node or leaf.
Definition: PCNode.h:62
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:472
PCTreeForest.h
PCTreeForests contain multiple PCTrees that can be merged with each other.
ogdf::pc_tree::PCNode::TempInfo::clear
void clear()
Definition: PCNode.h:108
ogdf::pc_tree::PCNode::m_temp
TempInfo m_temp
Definition: PCNode.h:141
ogdf::pc_tree::PCNode::LeafUserData
std::array< void *, sizeof(TempInfo)/sizeof(void *)> LeafUserData
Definition: PCNode.h:117
ogdf::NodeElement
Class for the representation of nodes.
Definition: Graph_d.h:240
ogdf::pc_tree::PCNode::~PCNode
~PCNode()
Definition: PCNode.h:154
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:296
ogdf::pc_tree::PCNode::flip
void flip()
Reverse the stored order of children.
Definition: PCNode.h:197