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
8using namespace bpp;
9using namespace std;
10
11
12/******************************************************************************/
13
14void TreeIterator::init()
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{
29 if (currNode_->hasFather())
30 {
32 for (size_t i = 0; i < currNode_->getFather()->getNumberOfSons(); ++i)
33 {
34 if (currNode_ == currNode_->getFather()->getSon(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 {
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
93 }
94
95 // update the returned node to be visited and its father's last visited son, if needed
97 if (currNode_->hasFather())
98 {
100 {
103 }
104 else
105 {
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
136 // else -> traverse to the leftmost brother which is right to currNode_ (also occurs when currNode has no sons
137 }
138 else
139 {
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 {
156 else
157 {
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 = 0; // jdutheil on 02/10/24: The init value is never used, but there to present a compilation warning.
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
222 {
224 }
225
226 // update the returned node to be visited and its father's last visited son, if needed
227 if (currNode_->hasFather())
228 {
231 else
232 {
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 * getFather() const
Get the father of this node is there is one.
Definition: Node.h:306
virtual const Node * getSon(size_t pos) const
Definition: Node.h:362
virtual bool isLeaf() const
Definition: Node.h:679
virtual bool hasFather() const
Tell if this node has a father node.
Definition: Node.h:346
virtual int getFatherId() const
Definition: Node.h:315
virtual size_t getNumberOfSons() const
Definition: Node.h:355
const Node * getLeftMostPredecessor(const Node *startNode)
TreeIterator & operator++()
const TreeTemplate< Node > & tree_
Definition: TreeIterator.h:38
const Node * begin()
map< int, bool > nodeToVisited_
Definition: TreeIterator.h:40
map< int, size_t > nodeToLastVisitedSonIndex_
Definition: TreeIterator.h:42
virtual const Node * next()=0
const Node * currNode_
Definition: TreeIterator.h:39
map< int, bool > nodeToSonVisited_
Definition: TreeIterator.h:41
Defines the basic types of data flow nodes.