aGrUM
3.2.0
a C++ library for (probabilistic) graphical models
Toggle main menu visibility
indexedTree_tpl.h
Go to the documentation of this file.
1
/****************************************************************************
2
* This file is part of the aGrUM/pyAgrum library. *
3
* *
4
* Copyright (c) 2005-2026 by *
5
* - Pierre-Henri WUILLEMIN(_at_LIP6) *
6
* - Christophe GONZALES(_at_AMU) *
7
* *
8
* The aGrUM/pyAgrum library is free software; you can redistribute it *
9
* and/or modify it under the terms of either : *
10
* *
11
* - the GNU Lesser General Public License as published by *
12
* the Free Software Foundation, either version 3 of the License, *
13
* or (at your option) any later version, *
14
* - the MIT license (MIT), *
15
* - or both in dual license, as here. *
16
* *
17
* (see https://agrum.gitlab.io/articles/dual-licenses-lgplv3mit.html) *
18
* *
19
* This aGrUM/pyAgrum library is distributed in the hope that it will be *
20
* useful, but WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
21
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES MERCHANTABILITY or FITNESS *
22
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
23
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
24
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
25
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
26
* OTHER DEALINGS IN THE SOFTWARE. *
27
* *
28
* See LICENCES for more details. *
29
* *
30
* SPDX-FileCopyrightText: Copyright 2005-2026 *
31
* - Pierre-Henri WUILLEMIN(_at_LIP6) *
32
* - Christophe GONZALES(_at_AMU) *
33
* SPDX-License-Identifier: LGPL-3.0-or-later OR MIT *
34
* *
35
* Contact : info_at_agrum_dot_org *
36
* homepage : http://agrum.gitlab.io *
37
* gitlab : https://gitlab.com/agrumery/agrum *
38
* *
39
****************************************************************************/
40
41
#pragma once
42
43
50
51
// to ease IDE parser
52
#include <
agrum/base/core/indexedTree.h
>
53
54
namespace
gum
{
55
/* =========================================================================*/
56
/* =========================================================================*/
57
/* === IMPLEMENTATION OF NODES FOR GENERIC TREE (DATA) STRUCTURE === */
58
/* =========================================================================*/
59
/* =========================================================================*/
60
61
// creates a tree with one node (with or without data)
62
63
template
<
typename
Key,
typename
Data >
64
IndexedTree< Key, Data >::IndexedTree
(
const
Key& theKey, Data* theData) :
65
key
(theKey),
data
(theData),
parent
(0) {
66
// for debugging purposes
67
GUM_CONSTRUCTOR(
IndexedTree
);
68
}
69
70
// creates a tree with one node (with or without data)
71
72
template
<
typename
Key,
typename
Data >
73
IndexedTree< Key, Data >::IndexedTree
(Data* theData) :
data
(theData),
parent
(0) {
74
// for debugging purposes
75
GUM_CONSTRUCTOR(
IndexedTree
);
76
}
77
78
// creates a tree with one node with data
79
80
template
<
typename
Key,
typename
Data >
81
IndexedTree< Key, Data >::IndexedTree
(
const
Key& theKey,
const
Data& theData) :
82
key
(theKey),
data
(new Data(theData)),
parent
(0) {
83
// for debugging purposes
84
GUM_CONSTRUCTOR(
IndexedTree
);
85
}
86
87
// copy constructor
88
89
template
<
typename
Key,
typename
Data >
90
IndexedTree< Key, Data >::IndexedTree
(
const
IndexedTree< Key, Data >
& from) :
91
key
(from.
key
),
data
(0),
parent
(0) {
92
// for debugging purposes
93
GUM_CONS_CPY(
IndexedTree
);
94
95
try
{
96
// create the data of the node
97
if
(from.
data
)
data
=
new
Data(*from.
data
);
98
99
// create and link properly the children
100
children
= from.
children
;
101
102
for
(
HashTableIteratorSafe
< Key,
IndexedTree< Key, Data >
> iter =
children
.begin();
103
iter !=
children
.end();
104
++iter)
105
iter->parent =
this
;
106
}
catch
(...) {
107
if
(
data
)
delete
data
;
108
109
children
.clear();
110
111
throw
;
112
}
113
}
114
115
// copy operator
116
117
template
<
typename
Key,
typename
Data >
118
IndexedTree< Key, Data >
&
119
IndexedTree< Key, Data >::operator=
(
const
IndexedTree< Key, Data >
& from) {
120
// avoid self assignment
121
if
(
this
!= &from) {
122
// for debugging purposes
123
GUM_OP_CPY(
IndexedTree
);
124
125
try
{
126
key
= from.
key
;
127
128
if
(
data
)
delete
data
;
129
130
if
(from.
data
)
data
=
new
Data(*from.
data
);
131
else
data
= 0;
132
133
children
= from.
children
;
134
135
for
(
HashTableIteratorSafe
< Key,
IndexedTree< Key, Data >
> iter =
children
.begin();
136
iter !=
children
.end();
137
++iter)
138
iter->parent =
this
;
139
}
catch
(...) {
140
if
(
data
)
delete
data
;
141
142
children
.clear();
143
144
throw
;
145
}
146
}
147
148
return
*
this
;
149
}
150
151
// destructor
152
153
template
<
typename
Key,
typename
Data >
154
IndexedTree< Key, Data >::~IndexedTree
() {
155
// for debugging purposes
156
GUM_DESTRUCTOR(
IndexedTree
);
157
158
if
(
data
)
delete
data
;
159
}
160
161
// adds a new node into the tree
162
163
template
<
typename
Key,
typename
Data >
164
void
IndexedTree< Key, Data >::insertNode
(
const
std::vector< Key >& index,
const
Data* theData) {
165
// parse the tree until we are on the proper index. Then, insert the new
166
// node.
167
// current_node is a pointer on the node of the tree corresponding to
168
// position
169
// i in vector index. When i+2 < index.size(), we need go down into the tree
170
// structure before we can insert the new node
171
IndexedTree< Key, Data >
* current_node =
this
;
172
unsigned
int
i;
173
174
for
(i = 0; i + 1 < index.size(); ++i) {
175
// if the node that should be on the path between the root of the tree and
176
// the node that we wish to insert does not exist, create it
177
if
(!
children
.exists(index[i])) {
178
IndexedTree< Key, Data >
* new_node =
new
IndexedTree< Key, Data >
(index[i], (Data*)0);
179
current_node->
children
.insert(index[i], new_node);
180
new_node->
parent
=
this
;
181
current_node = new_node;
182
}
else
current_node = current_node->
children
[index[i]];
183
}
184
185
// here, we can insert the new node. if ind + 1 == index.size(), this means
186
// that
187
// the index vector was not empty, else the vector was empty and we are at
188
// the
189
// root of the tree
190
if
(i + 1 == index.size()) {
191
// if the node to be inserted already exist, throw an exception
192
if
(current_node->
children
.exists(index[i])) {
193
GUM_ERROR
(
DuplicateElement
,
"the indexed tree already contains the node"
)
194
}
195
196
// here, the node to be inserted does not exist, so we must create it
197
IndexedTree< Key, Data >
* new_node
198
=
new
IndexedTree< Key, Data >
(index[i],
const_cast<
Data*
>
(theData));
199
200
current_node->
children
.insert(index[i], new_node);
201
202
new_node->
parent
= current_node;
203
}
else
{
204
// here, the node to be inserted is the root of the tree (so it already
205
// exists)
206
GUM_ERROR
(
DuplicateElement
,
"the indexed tree already contains the node"
)
207
}
208
}
209
210
// adds a new node into the tree
211
212
template
<
typename
Key,
typename
Data >
213
void
IndexedTree< Key, Data >::insertNode
(
const
std::vector< Key >& index,
const
Data& theData) {
214
// parse the tree until we are on the proper index. Then, insert the new
215
// node.
216
// current_node is a pointer on the node of the tree corresponding to
217
// position
218
// i in vector index. When i+2 < index.size(), we need go down into the tree
219
// structure before we can insert the new node
220
IndexedTree< Key, Data >
* current_node =
this
;
221
unsigned
int
i;
222
223
for
(i = 0; i + 1 < index.size(); ++i) {
224
// if the node that should be on the path between the root of the tree and
225
// the node that we wish to insert does not exist, create it
226
if
(!
children
.exists(index[i])) {
227
IndexedTree< Key, Data >
* new_node =
new
IndexedTree< Key, Data >
(index[i], (Data*)0);
228
current_node->
children
.insert(index[i], new_node);
229
new_node->
parent
=
this
;
230
current_node = new_node;
231
}
else
current_node = current_node->
children
[index[i]];
232
}
233
234
// here, we can insert the new node. if ind + 1 == index.size(), this means
235
// that
236
// the index vector was not empty, else the vector was empty and we are at
237
// the
238
// root of the tree
239
if
(i + 1 == index.size()) {
240
// if the node to be inserted already exist, throw an exception
241
if
(current_node->
children
.exists(index[i])) {
242
GUM_ERROR
(
DuplicateElement
,
"the indexed tree already contains the node"
)
243
}
244
245
// here, the node to be inserted does not exist, so we must create it
246
IndexedTree< Key, Data >
* new_node =
new
IndexedTree< Key, Data >
(index[i], theData);
247
248
current_node->
children
.insert(index[i], new_node);
249
250
new_node->
parent
= current_node;
251
}
else
{
252
// here, the node to be inserted is the root of the tree (so it already
253
// exists)
254
GUM_ERROR
(
DuplicateElement
,
"the indexed tree already contains the node"
)
255
}
256
}
257
258
// updates the value of a node (or adds it if it does not already exist)
259
260
template
<
typename
Key,
typename
Data >
261
void
IndexedTree< Key, Data >::setNode
(
const
std::vector< Key >& index, Data* theData) {
262
// parse the tree until we are on the proper index. Then, insert the new
263
// node.
264
// current_node is a pointer on the node of the tree corresponding to
265
// position
266
// i in vector index. When i+2 < index.size(), we need go down into the tree
267
// structure before we can insert the new node
268
IndexedTree< Key, Data >
* current_node =
this
;
269
unsigned
int
i;
270
271
for
(i = 0; i + 1 < index.size(); ++i) {
272
// if the node that should be on the path between the root of the tree and
273
// the node that we wish to insert does not exist, create it
274
if
(!
children
.exists(index[i])) {
275
IndexedTree< Key, Data >
* new_node =
new
IndexedTree< Key, Data >
(index[i], (Data*)0);
276
current_node->
children
.insert(index[i], new_node);
277
new_node->
parent
=
this
;
278
current_node = new_node;
279
}
else
current_node = current_node->
children
[index[i]];
280
}
281
282
// here, we can set the new node. if ind + 1 == index.size(), this means
283
// that
284
// the index vector was not empty, else the vector was empty and we are at
285
// the
286
// root of the tree
287
if
(i + 1 == index.size()) {
288
// if the node to be set does not exist, create it, else modify it
289
if
(current_node->
children
.exists(index[i])) {
290
IndexedTree< Key, Data >
* node = current_node->
children
[index[i]];
291
292
if
(node->
data
)
delete
node->
data
;
293
294
node->
data
= theData;
295
}
else
{
296
// here, the node tobe set does not exist, so we must create it
297
IndexedTree< Key, Data >
* new_node =
new
IndexedTree< Key, Data >
(index[i], theData);
298
current_node->
children
.insert(index[i], new_node);
299
new_node->
parent
= current_node;
300
}
301
}
else
{
302
// here, the node to be set is the root of the tree (so it does already
303
// exist
304
if
(
data
)
delete
data
;
305
306
data
= theData;
307
}
308
}
309
310
// updates the value of a node (or adds it if it does not already exist)
311
312
template
<
typename
Key,
typename
Data >
313
void
IndexedTree< Key, Data >::setNode
(
const
std::vector< Key >& index,
const
Data& theData) {
314
// parse the tree until we are on the proper index. Then, insert the new
315
// node.
316
// current_node is a pointer on the node of the tree corresponding to
317
// position
318
// i in vector index. When i+2 < index.size(), we need go down into the tree
319
// structure before we can insert the new node
320
IndexedTree< Key, Data >
* current_node =
this
;
321
unsigned
int
i;
322
323
for
(i = 0; i + 1 < index.size(); ++i) {
324
// if the node that should be on the path between the root of the tree and
325
// the node that we wish to insert does not exist, create it
326
if
(!
children
.exists(index[i])) {
327
IndexedTree< Key, Data >
* new_node =
new
IndexedTree< Key, Data >
(index[i], (Data*)0);
328
current_node->
children
.insert(index[i], new_node);
329
new_node->
parent
=
this
;
330
current_node = new_node;
331
}
else
current_node = current_node->
children
[index[i]];
332
}
333
334
// here, we can set the new node. if ind + 1 == index.size(), this means
335
// that
336
// the index vector was not empty, else the vector was empty and we are at
337
// the
338
// root of the tree
339
if
(i + 1 == index.size()) {
340
// if the node to be set does not exist, create it, else modify it
341
if
(current_node->
children
.exists(index[i])) {
342
IndexedTree< Key, Data >
* node = current_node->
children
[index[i]];
343
344
if
(node->
data
)
delete
node->
data
;
345
346
node->
data
=
new
Data(theData);
347
}
else
{
348
// here, the node tobe set does not exist, so we must create it
349
IndexedTree< Key, Data >
* new_node =
new
IndexedTree< Key, Data >
(index[i], theData);
350
current_node->
children
.insert(index[i], new_node);
351
new_node->
parent
= current_node;
352
}
353
}
else
{
354
// here, the node to be set is the root of the tree (so it does already
355
// exist
356
if
(
data
)
delete
data
;
357
358
data
=
new
Data(theData);
359
}
360
}
361
362
// returns the value of a given test from the cache
363
364
template
<
typename
Key,
typename
Data >
365
Data&
IndexedTree< Key, Data >::getData
(
const
std::vector< Key >& index)
const
{
366
IndexedTree< Key, Data >
* current_node =
const_cast<
IndexedTree< Key, Data >
*
>
(
this
);
367
368
for
(
unsigned
int
i = 0; i < index.size(); ++i)
369
current_node = current_node->
children
[index[i]];
370
371
if
(
data
== 0) {
GUM_ERROR
(
NotFound
,
"the datum could not be found"
) }
372
373
return
*(current_node->
data
);
374
}
375
376
// returns a given node of the tree
377
378
template
<
typename
Key,
typename
Data >
379
IndexedTree< Key, Data >
&
380
IndexedTree< Key, Data >::getNode
(
const
std::vector< Key >& index)
const
{
381
IndexedTree< Key, Data >
* current_node =
const_cast<
IndexedTree< Key, Data >
*
>
(
this
);
382
383
for
(
unsigned
int
i = 0; i < index.size(); ++i)
384
current_node = current_node->
children
[index[i]];
385
386
return
*current_node;
387
}
388
389
}
/* namespace gum */
HashTableIteratorSafe
Safe Iterators for hashtables.
DuplicateElement
Exception : a similar element already exists.
gum::IndexedTree
The class for storing the nodes of the Arborescence.
Definition
indexedTree.h:73
gum::IndexedTree::insertNode
void insertNode(const std::vector< Key > &index, const Data *data)
Adds a new node into the tree.
Definition
indexedTree_tpl.h:164
gum::IndexedTree::data
Data * data
The data stored into the node.
Definition
indexedTree.h:206
gum::IndexedTree::~IndexedTree
~IndexedTree()
Class destructor.
Definition
indexedTree_tpl.h:154
gum::IndexedTree::getNode
IndexedTree< Key, Data > & getNode(const std::vector< Key > &index) const
Returns a given node of the tree.
Definition
indexedTree_tpl.h:380
gum::IndexedTree::setNode
void setNode(const std::vector< Key > &index, Data *data)
Updates the value of a node (or adds it if it does not already exist).
Definition
indexedTree_tpl.h:261
gum::IndexedTree::children
HashTable< Key, IndexedTree< Key, Data > * > children
The list of children nodes of the current node.
Definition
indexedTree.h:212
gum::IndexedTree::key
Key key
The key of the current node.
Definition
indexedTree.h:203
gum::IndexedTree::getData
Data & getData(const std::vector< Key > &index) const
Returns the value of a given node of the tree.
Definition
indexedTree_tpl.h:365
gum::IndexedTree::parent
IndexedTree< Key, Data > * parent
The parent of the node.
Definition
indexedTree.h:209
gum::IndexedTree::operator=
IndexedTree< Key, Data > & operator=(const IndexedTree< Key, Data > &from)
Copy operator.
Definition
indexedTree_tpl.h:119
gum::IndexedTree::IndexedTree
IndexedTree(Data *data=nullptr)
Creates a tree with one node with or without data.
Definition
indexedTree_tpl.h:73
NotFound
Exception : the element we looked for cannot be found.
GUM_ERROR
#define GUM_ERROR(type, msg)
Definition
exceptions.h:76
indexedTree.h
Class for storing trees (as data structures, not graphs).
gum
gum is the global namespace for all aGrUM entities
Definition
agrum.h:46
aGrUM
3.2.0
© PHW&CG&others - 2022
DoXyGeN 1.18.0