aGrUM  0.20.2
a C++ library for (probabilistic) graphical models
indexedTree_tpl.h
Go to the documentation of this file.
1 /**
2  *
3  * Copyright 2005-2020 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  = children.begin();
82  iter != children.end();
83  ++iter)
84  iter->parent = this;
85  } catch (...) {
86  if (data) delete data;
87 
88  children.clear();
89 
90  throw;
91  }
92  }
93 
94  // copy operator
95 
96  template < typename Key, typename Data >
97  IndexedTree< Key, Data >&
99  // avoid self assignment
100  if (this != &from) {
101  // for debugging purposes
103 
104  try {
105  key = from.key;
106 
107  if (data) delete data;
108 
109  if (from.data)
110  data = new Data(*from.data);
111  else
112  data = 0;
113 
115 
117  = children.begin();
118  iter != children.end();
119  ++iter)
120  iter->parent = this;
121  } catch (...) {
122  if (data) delete data;
123 
124  children.clear();
125 
126  throw;
127  }
128  }
129 
130  return *this;
131  }
132 
133  // destructor
134 
135  template < typename Key, typename Data >
137  // for debugging purposes
139 
140  if (data) delete data;
141  }
142 
143  // adds a new node into the tree
144 
145  template < typename Key, typename Data >
147  const Data* theData) {
148  // parse the tree until we are on the proper index. Then, insert the new
149  // node.
150  // current_node is a pointer on the node of the tree corresponding to
151  // position
152  // i in vector index. When i+2 < index.size(), we need go down into the tree
153  // structure before we can insert the new node
154  IndexedTree< Key, Data >* current_node = this;
155  unsigned int i;
156 
157  for (i = 0; i + 1 < index.size(); ++i) {
158  // if the node that should be on the path between the root of the tree and
159  // the node that we wish to insert does not exist, create it
160  if (!children.exists(index[i])) {
162  = new IndexedTree< Key, Data >(index[i], (Data*)0);
164  new_node->parent = this;
166  } else
168  }
169 
170  // here, we can insert the new node. if ind + 1 == index.size(), this means
171  // that
172  // the index vector was not empty, else the vector was empty and we are at
173  // the
174  // root of the tree
175  if (i + 1 == index.size()) {
176  // if the node to be inserted already exist, throw an exception
178  GUM_ERROR(DuplicateElement, "the indexed tree already contains the node");
179  }
180 
181  // here, the node to be inserted does not exist, so we must create it
183  = new IndexedTree< Key, Data >(index[i], const_cast< Data* >(theData));
184 
186 
188  } else {
189  // here, the node to be inserted is the root of the tree (so it already
190  // exists)
191  GUM_ERROR(DuplicateElement, "the indexed tree already contains the node");
192  }
193  }
194 
195  // adds a new node into the tree
196 
197  template < typename Key, typename Data >
199  const Data& theData) {
200  // parse the tree until we are on the proper index. Then, insert the new
201  // node.
202  // current_node is a pointer on the node of the tree corresponding to
203  // position
204  // i in vector index. When i+2 < index.size(), we need go down into the tree
205  // structure before we can insert the new node
206  IndexedTree< Key, Data >* current_node = this;
207  unsigned int i;
208 
209  for (i = 0; i + 1 < index.size(); ++i) {
210  // if the node that should be on the path between the root of the tree and
211  // the node that we wish to insert does not exist, create it
212  if (!children.exists(index[i])) {
214  = new IndexedTree< Key, Data >(index[i], (Data*)0);
216  new_node->parent = this;
218  } else
220  }
221 
222  // here, we can insert the new node. if ind + 1 == index.size(), this means
223  // that
224  // the index vector was not empty, else the vector was empty and we are at
225  // the
226  // root of the tree
227  if (i + 1 == index.size()) {
228  // if the node to be inserted already exist, throw an exception
230  GUM_ERROR(DuplicateElement, "the indexed tree already contains the node");
231  }
232 
233  // here, the node to be inserted does not exist, so we must create it
235  = new IndexedTree< Key, Data >(index[i], theData);
236 
238 
240  } else {
241  // here, the node to be inserted is the root of the tree (so it already
242  // exists)
243  GUM_ERROR(DuplicateElement, "the indexed tree already contains the node");
244  }
245  }
246 
247  // updates the value of a node (or adds it if it does not already exist)
248 
249  template < typename Key, typename Data >
250  void IndexedTree< Key, Data >::setNode(const std::vector< Key >& index,
251  Data* theData) {
252  // parse the tree until we are on the proper index. Then, insert the new
253  // node.
254  // current_node is a pointer on the node of the tree corresponding to
255  // position
256  // i in vector index. When i+2 < index.size(), we need go down into the tree
257  // structure before we can insert the new node
258  IndexedTree< Key, Data >* current_node = this;
259  unsigned int i;
260 
261  for (i = 0; i + 1 < index.size(); ++i) {
262  // if the node that should be on the path between the root of the tree and
263  // the node that we wish to insert does not exist, create it
264  if (!children.exists(index[i])) {
266  = new IndexedTree< Key, Data >(index[i], (Data*)0);
268  new_node->parent = this;
270  } else
272  }
273 
274  // here, we can set the new node. if ind + 1 == index.size(), this means
275  // that
276  // the index vector was not empty, else the vector was empty and we are at
277  // the
278  // root of the tree
279  if (i + 1 == index.size()) {
280  // if the node to be set does not exist, create it, else modify it
283 
284  if (node->data) delete node->data;
285 
286  node->data = theData;
287  } else {
288  // here, the node tobe set does not exist, so we must create it
290  = new IndexedTree< Key, Data >(index[i], theData);
293  }
294  } else {
295  // here, the node to be set is the root of the tree (so it does already
296  // exist
297  if (data) delete data;
298 
299  data = theData;
300  }
301  }
302 
303  // updates the value of a node (or adds it if it does not already exist)
304 
305  template < typename Key, typename Data >
306  void IndexedTree< Key, Data >::setNode(const std::vector< Key >& index,
307  const Data& theData) {
308  // parse the tree until we are on the proper index. Then, insert the new
309  // node.
310  // current_node is a pointer on the node of the tree corresponding to
311  // position
312  // i in vector index. When i+2 < index.size(), we need go down into the tree
313  // structure before we can insert the new node
314  IndexedTree< Key, Data >* current_node = this;
315  unsigned int i;
316 
317  for (i = 0; i + 1 < index.size(); ++i) {
318  // if the node that should be on the path between the root of the tree and
319  // the node that we wish to insert does not exist, create it
320  if (!children.exists(index[i])) {
322  = new IndexedTree< Key, Data >(index[i], (Data*)0);
324  new_node->parent = this;
326  } else
328  }
329 
330  // here, we can set the new node. if ind + 1 == index.size(), this means
331  // that
332  // the index vector was not empty, else the vector was empty and we are at
333  // the
334  // root of the tree
335  if (i + 1 == index.size()) {
336  // if the node to be set does not exist, create it, else modify it
339 
340  if (node->data) delete node->data;
341 
342  node->data = new Data(theData);
343  } else {
344  // here, the node tobe set does not exist, so we must create it
346  = new IndexedTree< Key, Data >(index[i], theData);
349  }
350  } else {
351  // here, the node to be set is the root of the tree (so it does already
352  // exist
353  if (data) delete data;
354 
355  data = new Data(theData);
356  }
357  }
358 
359  // returns the value of a given test from the cache
360 
361  template < typename Key, typename Data >
362  INLINE Data&
363  IndexedTree< Key, Data >::getData(const std::vector< Key >& index) const {
365  = const_cast< IndexedTree< Key, Data >* >(this);
366 
367  for (unsigned int i = 0; i < index.size(); ++i)
369 
370  if (data == 0) { GUM_ERROR(NotFound, "the datum could not be found"); }
371 
372  return *(current_node->data);
373  }
374 
375  // returns a given node of the tree
376 
377  template < typename Key, typename Data >
379  IndexedTree< Key, Data >::getNode(const std::vector< Key >& index) const {
381  = const_cast< IndexedTree< Key, Data >* >(this);
382 
383  for (unsigned int i = 0; i < index.size(); ++i)
385 
386  return *current_node;
387  }
388 
389 } /* namespace gum */
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:669