bpp-phyl3  3.0.0
TreeIterator.cpp
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: The Bio++ Development Group
2 //
3 // SPDX-License-Identifier: CECILL-2.1
4 
5 #include "TreeIterator.h"
6 
7 // imports from bpp-core
8 using namespace bpp;
9 using namespace std;
10 
11 
12 /******************************************************************************/
13 
15 {
16  vector<const Node*> nodes = tree_.getNodes();
17  for (size_t i = 0; i < nodes.size(); ++i)
18  {
19  nodeToVisited_[nodes[i]->getId()] = false;
20  nodeToSonVisited_[nodes[i]->getId()] = false;
21  }
22 }
23 
24 /******************************************************************************/
25 
27 {
28  nodeToVisited_[currNode_->getId()] = true;
29  if (currNode_->hasFather())
30  {
31  nodeToSonVisited_[currNode_->getFatherId()] = true;
32  for (size_t i = 0; i < currNode_->getFather()->getNumberOfSons(); ++i)
33  {
34  if (currNode_ == currNode_->getFather()->getSon(i))
35  nodeToLastVisitedSonIndex_[currNode_->getFatherId()] = i;
36  }
37  }
38  return currNode_;
39 }
40 
41 /******************************************************************************/
42 
44 {
45  this->next();
46  return *this;
47 }
48 
49 /******************************************************************************/
50 
52 {
53  size_t nextPos = 0;
54  if (nodeToSonVisited_[startNode->getId()])
55  nextPos = nodeToLastVisitedSonIndex_[startNode->getId()] + 1;
56  // if startNode has no predecessors -> move to him
57  if (nextPos >= startNode->getNumberOfSons())
58  {
59  return startNode;
60  }
61  const Node* node = startNode->getSon(nextPos);
62  while (node->getNumberOfSons() > 0)
63  {
64  node = node->getSon(0);
65  }
66  return node;
67 }
68 
69 /******************************************************************************/
70 
72 { // order: (left, right, parent)
73  // stop condition: currNode_ is root
74  if (!currNode_->hasFather())
75  {
76  return NULL;
77  }
78 
79  // by the time you visit currNode_, all the nodes in its subtree were already visited
80  size_t numOfBrothers = currNode_->getFather()->getNumberOfSons(); // get the number of brothers of currNode_
81  size_t lastVisitedBrotherPos = nodeToLastVisitedSonIndex_[currNode_->getFatherId()]; // since currNode is already visited, its father must have at least one visited son (which is currNode_)
82  // if all the brothers were already visited -> now visit the father
83  if (lastVisitedBrotherPos == numOfBrothers - 1)
84  {
85  currNode_ = currNode_->getFather();
86  }
87  // else -> visit the leftmost predecessor next brother on the list
88  else
89  {
90  size_t nextSiblingPos = lastVisitedBrotherPos + 1;
91  currNode_ = currNode_->getFather()->getSon(nextSiblingPos); // the next brother is not visited yet if its has a non-visited leftmost predecessor
92  currNode_ = getLeftMostPredecessor(currNode_);
93  }
94 
95  // update the returned node to be visited and its father's last visited son, if needed
96  nodeToVisited_[currNode_->getId()] = true;
97  if (currNode_->hasFather())
98  {
99  if (!nodeToSonVisited_[currNode_->getFatherId()])
100  {
101  nodeToSonVisited_[currNode_->getFatherId()] = true;
102  nodeToLastVisitedSonIndex_[currNode_->getFatherId()] = 0;
103  }
104  else
105  {
106  nodeToLastVisitedSonIndex_[currNode_->getFatherId()] = nodeToLastVisitedSonIndex_[currNode_->getFatherId()] + 1;
107  }
108  }
109  return currNode_;
110 }
111 
112 /******************************************************************************/
113 
115 { // order: (parent, left, right)
116  vector<int> leafIds = tree_.getLeavesId();
117  bool hasVisitedSons = nodeToSonVisited_[currNode_->getId()];
118  size_t numOfSons = currNode_->getNumberOfSons();
119 
120  // stop condition: the node is the rightmost leaf of the tree
121  if (currNode_->getId() == leafIds[leafIds.size() - 1])
122  {
123  return NULL;
124  }
125 
126  // by the time you visit currNode_, all its ancestors and left brothers (if exist) were already visited
127  if (!hasVisitedSons && numOfSons > 0)
128  {
129  currNode_ = currNode_->getSon(0); // this somehow modifies the value of nodeToSonVisited_[currNode_->getFatherId()] to true... how?
130  }
131  // as long as there are still sons to visit -> visit the leftmost unvisited son
132  else if (hasVisitedSons && nodeToLastVisitedSonIndex_[currNode_->getId()] < numOfSons - 1)
133  {
134  // if this point is reached, the current node already has visited sons, or it has no sons at all and we are done
135  currNode_ = currNode_->getSon(nodeToLastVisitedSonIndex_[currNode_->getId()] + 1);
136  // else -> traverse to the leftmost brother which is right to currNode_ (also occurs when currNode has no sons
137  }
138  else
139  {
140  currNode_ = currNode_->getFather();
141  size_t lastVisitedSonPos = nodeToLastVisitedSonIndex_[currNode_->getId()]; // the father of the original currNode_ must have at least one visited child which is the original currNode_
142  numOfSons = currNode_->getNumberOfSons();
143  while (lastVisitedSonPos == numOfSons - 1)
144  {
145  currNode_ = currNode_->getFather(); // the father node must have visited sons as the currNode is a visited son of his
146  lastVisitedSonPos = nodeToLastVisitedSonIndex_[currNode_->getId()];
147  numOfSons = currNode_->getNumberOfSons();
148  }
149  currNode_ = currNode_->getSon(lastVisitedSonPos + 1); // need to remove +1??
150  }
151  // update the returned node to be visited and its father's last visited son, if needed
152  if (currNode_->hasFather())
153  {
154  if (nodeToSonVisited_[currNode_->getFatherId()])
155  nodeToLastVisitedSonIndex_[currNode_->getFatherId()] = nodeToLastVisitedSonIndex_[currNode_->getFatherId()] + 1;
156  else
157  {
158  nodeToSonVisited_[currNode_->getFatherId()] = true;
159  nodeToLastVisitedSonIndex_[currNode_->getFatherId()] = 0;
160  }
161  }
162  nodeToVisited_[currNode_->getId()] = true;
163  return currNode_;
164 }
165 
166 /******************************************************************************/
167 
169 {
170  // if the node has unvisited left sons -> visit the leftmost unvisited son
171  size_t lastVisitedSon;
172  if (nodeToSonVisited_[node->getId()])
173  lastVisitedSon = nodeToLastVisitedSonIndex_[node->getId()];
174  size_t numOfSons = node->getNumberOfSons();
175  bool is_visited = nodeToVisited_[node->getId()];
176 
177  // if the node has unvisited left sons - go to the leftmost unvisited son
178  if (!nodeToSonVisited_[node->getId()] && numOfSons > 0)
179  {
180  return node->getSon(0);
181  }
182  else if (nodeToSonVisited_[node->getId()] && lastVisitedSon < static_cast<size_t>(floor(numOfSons / 2) - 1))
183  {
184  return node->getSon(lastVisitedSon + 1);
185  }
186 
187  // if the node last visited its last left son or is a not yet visited leaf / parent of a single node -> go to it
188  else if (numOfSons > 1 && lastVisitedSon == static_cast<size_t>(floor(numOfSons / 2) - 1) && !is_visited)
189  {
190  return node;
191  }
192 
193  // if the node has unvisited right sons -> go to the leftmost unvisited right son
194  else if (nodeToSonVisited_[node->getId()] && lastVisitedSon < numOfSons - 1)
195  {
196  return node->getSon(lastVisitedSon + 1);
197  }
198 
199  // else - the entire subtree of the node has been scanned - move to its father
200  else
201  {
202  return node->getFather();
203  }
204 }
205 
206 
207 /******************************************************************************/
208 
210 { // order: (left (0,..,n/2-1), parent, right (n/2,....,n))
211  vector<int> leafIds = tree_.getLeavesId();
212 
213  // stop condition: the node is the rightmost leaf of the tree
214  if (currNode_->getId() == leafIds[leafIds.size() - 1])
215  {
216  return NULL;
217  }
218 
219  // while curNode still has unvisited left sons -> do another step
220  while (nodeToVisited_[currNode_->getId()]
221  || (!nodeToSonVisited_[currNode_->getId()] && !currNode_->isLeaf()) || (nodeToSonVisited_[currNode_->getId()] && nodeToLastVisitedSonIndex_[currNode_->getId()] < static_cast<size_t>(floor(currNode_->getNumberOfSons() / 2) - 1) && !currNode_->isLeaf()))
222  {
223  currNode_ = doStep(currNode_);
224  }
225 
226  // update the returned node to be visited and its father's last visited son, if needed
227  if (currNode_->hasFather())
228  {
229  if (nodeToSonVisited_[currNode_->getFatherId()])
230  nodeToLastVisitedSonIndex_[currNode_->getFatherId()] = nodeToLastVisitedSonIndex_[currNode_->getFatherId()] + 1;
231  else
232  {
233  nodeToSonVisited_[currNode_->getFatherId()] = true;
234  nodeToLastVisitedSonIndex_[currNode_->getFatherId()] = 0;
235  }
236  }
237  nodeToVisited_[currNode_->getId()] = true;
238  return currNode_;
239 }
const Node * doStep(const Node *node)
The phylogenetic node class.
Definition: Node.h:59
virtual int getId() const
Get the node's id.
Definition: Node.h:170
virtual const Node * getSon(size_t pos) const
Definition: Node.h:362
virtual const Node * getFather() const
Get the father of this node is there is one.
Definition: Node.h:306
virtual size_t getNumberOfSons() const
Definition: Node.h:355
const Node * getLeftMostPredecessor(const Node *startNode)
TreeIterator & operator++()
const Node * begin()
Defines the basic types of data flow nodes.