aGrUM  0.20.3
a C++ library for (probabilistic) graphical models
indexedTree_tpl.h
Go to the documentation of this file.
1 /**
2  *
3  * Copyright (c) 2005-2021 by Pierre-Henri WUILLEMIN(@LIP6) & Christophe GONZALES(@AMU)
4  * info_at_agrum_dot_org
5  *
6  * This library is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this library. If not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20 
21 
22 /**
23  * @file
24  * @brief Implementation of tree data structures
25  *
26  * @author Christophe GONZALES(@AMU) and Pierre-Henri WUILLEMIN(@LIP6)
27  */
28 
29 // to ease IDE parser
30 #include <agrum/tools/core/indexedTree.h>
31 
32 namespace gum {
33  /* =========================================================================*/
34  /* =========================================================================*/
35  /* === IMPLEMENTATION OF NODES FOR GENERIC TREE (DATA) STRUCTURE === */
36  /* =========================================================================*/
37  /* =========================================================================*/
38 
39  // creates a tree with one node (with or without data)
40 
41  template < typename Key, typename Data >
42  IndexedTree< Key, Data >::IndexedTree(const Key& theKey, Data* theData) :
43  key(theKey), data(theData), parent(0) {
44  // for debugging purposes
45  GUM_CONSTRUCTOR(IndexedTree);
46  }
47 
48  // creates a tree with one node (with or without data)
49 
50  template < typename Key, typename Data >
52  // for debugging purposes
54  }
55 
56  // creates a tree with one node with data
57 
58  template < typename Key, typename Data >
60  key(theKey), data(new Data(theData)), parent(0) {
61  // for debugging purposes
63  }
64 
65  // copy constructor
66 
67  template < typename Key, typename Data >
69  key(from.key), data(0), parent(0) {
70  // for debugging purposes
72 
73  try {
74  // create the data of the node
75  if (from.data) data = new Data(*from.data);
76 
77  // create and link properly the children
79 
81  iter != children.end();
82  ++iter)
83  iter->parent = this;
84  } catch (...) {
85  if (data) delete data;
86 
87  children.clear();
88 
89  throw;
90  }
91  }
92 
93  // copy operator
94 
95  template < typename Key, typename Data >
96  IndexedTree< Key, Data >&
98  // avoid self assignment
99  if (this != &from) {
100  // for debugging purposes
102 
103  try {
104  key = from.key;
105 
106  if (data) delete data;
107 
108  if (from.data)
109  data = new Data(*from.data);
110  else
111  data = 0;
112 
114 
116  iter != children.end();
117  ++iter)
118  iter->parent = this;
119  } catch (...) {
120  if (data) delete data;
121 
122  children.clear();
123 
124  throw;
125  }
126  }
127 
128  return *this;
129  }
130 
131  // destructor
132 
133  template < typename Key, typename Data >
135  // for debugging purposes
137 
138  if (data) delete data;
139  }
140 
141  // adds a new node into the tree
142 
143  template < typename Key, typename Data >
144  void IndexedTree< Key, Data >::insertNode(const std::vector< Key >& index, const Data* theData) {
145  // parse the tree until we are on the proper index. Then, insert the new
146  // node.
147  // current_node is a pointer on the node of the tree corresponding to
148  // position
149  // i in vector index. When i+2 < index.size(), we need go down into the tree
150  // structure before we can insert the new node
151  IndexedTree< Key, Data >* current_node = this;
152  unsigned int i;
153 
154  for (i = 0; i + 1 < index.size(); ++i) {
155  // if the node that should be on the path between the root of the tree and
156  // the node that we wish to insert does not exist, create it
157  if (!children.exists(index[i])) {
158  IndexedTree< Key, Data >* new_node = new IndexedTree< Key, Data >(index[i], (Data*)0);
160  new_node->parent = this;
162  } else
164  }
165 
166  // here, we can insert the new node. if ind + 1 == index.size(), this means
167  // that
168  // the index vector was not empty, else the vector was empty and we are at
169  // the
170  // root of the tree
171  if (i + 1 == index.size()) {
172  // if the node to be inserted already exist, throw an exception
174  GUM_ERROR(DuplicateElement, "the indexed tree already contains the node")
175  }
176 
177  // here, the node to be inserted does not exist, so we must create it
179  = new IndexedTree< Key, Data >(index[i], const_cast< Data* >(theData));
180 
182 
184  } else {
185  // here, the node to be inserted is the root of the tree (so it already
186  // exists)
187  GUM_ERROR(DuplicateElement, "the indexed tree already contains the node")
188  }
189  }
190 
191  // adds a new node into the tree
192 
193  template < typename Key, typename Data >
194  void IndexedTree< Key, Data >::insertNode(const std::vector< Key >& index, const Data& theData) {
195  // parse the tree until we are on the proper index. Then, insert the new
196  // node.
197  // current_node is a pointer on the node of the tree corresponding to
198  // position
199  // i in vector index. When i+2 < index.size(), we need go down into the tree
200  // structure before we can insert the new node
201  IndexedTree< Key, Data >* current_node = this;
202  unsigned int i;
203 
204  for (i = 0; i + 1 < index.size(); ++i) {
205  // if the node that should be on the path between the root of the tree and
206  // the node that we wish to insert does not exist, create it
207  if (!children.exists(index[i])) {
208  IndexedTree< Key, Data >* new_node = new IndexedTree< Key, Data >(index[i], (Data*)0);
210  new_node->parent = this;
212  } else
214  }
215 
216  // here, we can insert the new node. if ind + 1 == index.size(), this means
217  // that
218  // the index vector was not empty, else the vector was empty and we are at
219  // the
220  // root of the tree
221  if (i + 1 == index.size()) {
222  // if the node to be inserted already exist, throw an exception
224  GUM_ERROR(DuplicateElement, "the indexed tree already contains the node")
225  }
226 
227  // here, the node to be inserted does not exist, so we must create it
229 
231 
233  } else {
234  // here, the node to be inserted is the root of the tree (so it already
235  // exists)
236  GUM_ERROR(DuplicateElement, "the indexed tree already contains the node")
237  }
238  }
239 
240  // updates the value of a node (or adds it if it does not already exist)
241 
242  template < typename Key, typename Data >
243  void IndexedTree< Key, Data >::setNode(const std::vector< Key >& index, Data* theData) {
244  // parse the tree until we are on the proper index. Then, insert the new
245  // node.
246  // current_node is a pointer on the node of the tree corresponding to
247  // position
248  // i in vector index. When i+2 < index.size(), we need go down into the tree
249  // structure before we can insert the new node
250  IndexedTree< Key, Data >* current_node = this;
251  unsigned int i;
252 
253  for (i = 0; i + 1 < index.size(); ++i) {
254  // if the node that should be on the path between the root of the tree and
255  // the node that we wish to insert does not exist, create it
256  if (!children.exists(index[i])) {
257  IndexedTree< Key, Data >* new_node = new IndexedTree< Key, Data >(index[i], (Data*)0);
259  new_node->parent = this;
261  } else
263  }
264 
265  // here, we can set the new node. if ind + 1 == index.size(), this means
266  // that
267  // the index vector was not empty, else the vector was empty and we are at
268  // the
269  // root of the tree
270  if (i + 1 == index.size()) {
271  // if the node to be set does not exist, create it, else modify it
274 
275  if (node->data) delete node->data;
276 
277  node->data = theData;
278  } else {
279  // here, the node tobe set does not exist, so we must create it
283  }
284  } else {
285  // here, the node to be set is the root of the tree (so it does already
286  // exist
287  if (data) delete data;
288 
289  data = theData;
290  }
291  }
292 
293  // updates the value of a node (or adds it if it does not already exist)
294 
295  template < typename Key, typename Data >
296  void IndexedTree< Key, Data >::setNode(const std::vector< Key >& index, const Data& theData) {
297  // parse the tree until we are on the proper index. Then, insert the new
298  // node.
299  // current_node is a pointer on the node of the tree corresponding to
300  // position
301  // i in vector index. When i+2 < index.size(), we need go down into the tree
302  // structure before we can insert the new node
303  IndexedTree< Key, Data >* current_node = this;
304  unsigned int i;
305 
306  for (i = 0; i + 1 < index.size(); ++i) {
307  // if the node that should be on the path between the root of the tree and
308  // the node that we wish to insert does not exist, create it
309  if (!children.exists(index[i])) {
310  IndexedTree< Key, Data >* new_node = new IndexedTree< Key, Data >(index[i], (Data*)0);
312  new_node->parent = this;
314  } else
316  }
317 
318  // here, we can set the new node. if ind + 1 == index.size(), this means
319  // that
320  // the index vector was not empty, else the vector was empty and we are at
321  // the
322  // root of the tree
323  if (i + 1 == index.size()) {
324  // if the node to be set does not exist, create it, else modify it
327 
328  if (node->data) delete node->data;
329 
330  node->data = new Data(theData);
331  } else {
332  // here, the node tobe set does not exist, so we must create it
336  }
337  } else {
338  // here, the node to be set is the root of the tree (so it does already
339  // exist
340  if (data) delete data;
341 
342  data = new Data(theData);
343  }
344  }
345 
346  // returns the value of a given test from the cache
347 
348  template < typename Key, typename Data >
349  INLINE Data& IndexedTree< Key, Data >::getData(const std::vector< Key >& index) const {
350  IndexedTree< Key, Data >* current_node = const_cast< IndexedTree< Key, Data >* >(this);
351 
352  for (unsigned int i = 0; i < index.size(); ++i)
354 
355  if (data == 0) { GUM_ERROR(NotFound, "the datum could not be found") }
356 
357  return *(current_node->data);
358  }
359 
360  // returns a given node of the tree
361 
362  template < typename Key, typename Data >
364  IndexedTree< Key, Data >::getNode(const std::vector< Key >& index) const {
365  IndexedTree< Key, Data >* current_node = const_cast< IndexedTree< Key, Data >* >(this);
366 
367  for (unsigned int i = 0; i < index.size(); ++i)
369 
370  return *current_node;
371  }
372 
373 } /* namespace gum */
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:643