aGrUM
0.20.2
a C++ library for (probabilistic) graphical models
binTreeNode_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 Node class for various binary search trees
25
*
26
* @author Christophe GONZALES(@AMU) and Pierre-Henri WUILLEMIN(@LIP6)
27
*/
28
29
#
ifndef
DOXYGEN_SHOULD_SKIP_THIS
30
31
namespace
gum
{
32
33
template
<
typename
Val >
34
INLINE BinTreeNode<
Val
>::
BinTreeNode
(
const
Val
&
v
) :
35
val_
(
v
),
parent_
(0),
parent_dir_
(
BinTreeDir
::
NO_PARENT
) {
36
// for debugging purposes
37
GUM_CONSTRUCTOR
(
BinTreeNode
);
38
39
// set the children
40
children_
[0] =
nullptr
;
41
children_
[1] =
nullptr
;
42
}
43
44
template
<
typename
Val
>
45
INLINE
BinTreeNode
<
Val
>::
BinTreeNode
(
const
BinTreeNode
<
Val
>&
from
) :
46
val_
(
from
.
val_
),
parent_
(0),
parent_dir_
(
BinTreeDir
::
NO_PARENT
) {
47
// for debugging purposes
48
GUM_CONS_CPY
(
BinTreeNode
);
49
50
// set the children
51
children_
[0] =
nullptr
;
52
children_
[1] =
nullptr
;
53
}
54
55
template
<
typename
Val
>
56
INLINE
BinTreeNode
<
Val
>::~
BinTreeNode
() {
57
// for debugging purposes
58
GUM_DESTRUCTOR
(
BinTreeNode
);
59
60
// update the tree accordingly to the removal of this
61
if
(
parent_
)
62
parent_
->
children_
[
static_cast
<
int
>(
parent_dir_
)]
63
=
nullptr
;
// parent_dir can not be NO_PARENT (... sure ?)
64
65
if
(
children_
[0]) {
66
children_
[0]->
parent_
=
nullptr
;
67
children_
[0]->
parent_dir_
=
BinTreeDir
::
NO_PARENT
;
68
}
69
70
if
(
children_
[1]) {
71
children_
[1]->
parent_
=
nullptr
;
72
children_
[1]->
parent_dir_
=
BinTreeDir
::
NO_PARENT
;
73
}
74
}
75
76
/** @brief copy operator: copy the value of from into this. However, this
77
* does not change the current connections (parents and children) of this. */
78
79
template
<
typename
Val
>
80
INLINE
BinTreeNode
<
Val
>&
81
BinTreeNode
<
Val
>::
operator
=(
const
BinTreeNode
<
Val
>&
from
) {
82
// avoid self assignment
83
if
(
this
!= &
from
) {
84
GUM_OP_CPY
(
BinTreeNode
);
85
val_
=
from
.
val_
;
86
}
87
88
return
*
this
;
89
}
90
91
template
<
typename
Val
>
92
INLINE
Val
&
BinTreeNode
<
Val
>::
value
() {
93
return
val_
;
94
}
95
96
template
<
typename
Val
>
97
INLINE
Val
&
BinTreeNode
<
Val
>::
operator
*() {
98
return
val_
;
99
}
100
101
template
<
typename
Val
>
102
INLINE
BinTreeNode
<
Val
>*
BinTreeNode
<
Val
>::
child
(
BinTreeDir
dir
)
const
{
103
return
children_
[
static_cast
<
int
>(
dir
)];
104
}
105
106
template
<
typename
Val
>
107
INLINE
BinTreeNode
<
Val
>*
BinTreeNode
<
Val
>::
leftChild
()
const
{
108
return
children_
[
static_cast
<
int
>(
BinTreeDir
::
LEFT_CHILD
)];
109
}
110
111
template
<
typename
Val
>
112
INLINE
BinTreeNode
<
Val
>*
BinTreeNode
<
Val
>::
rightChild
()
const
{
113
return
children_
[
static_cast
<
int
>(
BinTreeDir
::
RIGHT_CHILD
)];
114
}
115
116
template
<
typename
Val
>
117
INLINE
BinTreeNode
<
Val
>*
BinTreeNode
<
Val
>::
parent
()
const
{
118
return
parent_
;
119
}
120
121
template
<
typename
Val
>
122
INLINE
BinTreeDir
BinTreeNode
<
Val
>::
parentDir
()
const
{
123
return
parent_dir_
;
124
}
125
126
template
<
typename
Val
>
127
INLINE
void
BinTreeNode
<
Val
>::
insertLeftChild
(
BinTreeNode
<
Val
>&
new_child
) {
128
if
(
new_child
.
parent_
) {
129
GUM_ERROR
(
DuplicateElement
,
"this child already has a parent in the BST"
);
130
}
131
132
if
(
children_
[
static_cast
<
int
>(
BinTreeDir
::
LEFT_CHILD
)]) {
133
GUM_ERROR
(
DuplicateElement
,
"this child already has a parent in the BST"
);
134
}
135
136
// proceed to the chaining
137
new_child
.
parent_
=
this
;
138
new_child
.
parent_dir_
=
BinTreeDir
::
LEFT_CHILD
;
139
children_
[
static_cast
<
int
>(
BinTreeDir
::
LEFT_CHILD
)] = &
new_child
;
140
}
141
142
template
<
typename
Val
>
143
INLINE
BinTreeNode
<
Val
>*
BinTreeNode
<
Val
>::
insertLeftChild
(
const
Val
&
val
) {
144
if
(
children_
[
static_cast
<
int
>(
BinTreeDir
::
LEFT_CHILD
)]) {
145
GUM_ERROR
(
DuplicateElement
,
"this child already has a parent in the BST"
);
146
}
147
148
BinTreeNode
<
Val
>*
new_child
=
new
BinTreeNode
<
Val
>(
val
);
149
150
// proceed to the chaining
151
new_child
->
parent_
=
this
;
152
new_child
->
parent_dir_
=
BinTreeDir
::
LEFT_CHILD
;
153
children_
[
static_cast
<
int
>(
BinTreeDir
::
LEFT_CHILD
)] =
new_child
;
154
155
return
new_child
;
156
}
157
158
template
<
typename
Val
>
159
INLINE
void
BinTreeNode
<
Val
>::
insertRightChild
(
BinTreeNode
<
Val
>&
new_child
) {
160
if
(
new_child
.
parent_
) {
161
GUM_ERROR
(
DuplicateElement
,
"this child already has a parent in the BST"
);
162
}
163
164
if
(
children_
[
static_cast
<
int
>(
BinTreeDir
::
RIGHT_CHILD
)]) {
165
GUM_ERROR
(
DuplicateElement
,
"this node already has a right child"
);
166
}
167
168
// proceed to the chaining
169
new_child
.
parent_
=
this
;
170
new_child
.
parent_dir_
=
BinTreeDir
::
RIGHT_CHILD
;
171
children_
[
static_cast
<
int
>(
BinTreeDir
::
RIGHT_CHILD
)] = &
new_child
;
172
}
173
174
template
<
typename
Val
>
175
INLINE
BinTreeNode
<
Val
>*
BinTreeNode
<
Val
>::
insertRightChild
(
const
Val
&
val
) {
176
if
(
children_
[
static_cast
<
int
>(
BinTreeDir
::
RIGHT_CHILD
)]) {
177
GUM_ERROR
(
DuplicateElement
,
"this node already has a right child"
);
178
}
179
180
BinTreeNode
<
Val
>*
new_child
=
new
BinTreeNode
<
Val
>(
val
);
181
182
// proceed to the chaining
183
new_child
->
parent_
=
this
;
184
new_child
->
parent_dir_
=
BinTreeDir
::
RIGHT_CHILD
;
185
children_
[
static_cast
<
int
>(
BinTreeDir
::
RIGHT_CHILD
)] =
new_child
;
186
187
return
new_child
;
188
}
189
190
template
<
typename
Val
>
191
INLINE
void
BinTreeNode
<
Val
>::
insertChild
(
BinTreeNode
<
Val
>&
new_child
,
192
BinTreeDir
child_dir
) {
193
if
(
new_child
.
parent_
) {
194
GUM_ERROR
(
DuplicateElement
,
"this child has already a parent"
);
195
}
196
197
if
(
children_
[
static_cast
<
int
>(
child_dir
)]) {
198
GUM_ERROR
(
DuplicateElement
,
"this node has already this child"
);
199
}
200
201
// proceed to the chaining
202
new_child
.
parent_
=
this
;
203
new_child
.
parent_dir_
=
child_dir
;
204
children_
[
static_cast
<
int
>(
child_dir
)] = &
new_child
;
205
}
206
207
template
<
typename
Val
>
208
INLINE
BinTreeNode
<
Val
>*
209
BinTreeNode
<
Val
>::
insertChild
(
const
Val
&
val
,
BinTreeDir
child_dir
) {
210
if
(
children_
[
static_cast
<
int
>(
child_dir
)]) {
211
GUM_ERROR
(
DuplicateElement
,
"this node has already this child"
);
212
}
213
214
BinTreeNode
<
Val
>*
new_child
=
new
BinTreeNode
<
Val
>(
val
);
215
216
// proceed to the chaining
217
new_child
->
parent_
=
this
;
218
new_child
->
parent_dir_
=
child_dir
;
219
children_
[
static_cast
<
int
>(
child_dir
)] =
new_child
;
220
221
return
new_child
;
222
}
223
224
template
<
typename
Val
>
225
INLINE
void
BinTreeNode
<
Val
>::
eraseLeftLink
() {
226
if
(
children_
[
static_cast
<
int
>(
BinTreeDir
::
LEFT_CHILD
)]) {
227
children_
[
static_cast
<
int
>(
BinTreeDir
::
LEFT_CHILD
)]->
parent_
=
nullptr
;
228
children_
[
static_cast
<
int
>(
BinTreeDir
::
LEFT_CHILD
)]->
parent_dir_
229
=
BinTreeDir
::
NO_PARENT
;
230
children_
[
static_cast
<
int
>(
BinTreeDir
::
LEFT_CHILD
)] =
nullptr
;
231
}
232
}
233
234
template
<
typename
Val
>
235
INLINE
void
BinTreeNode
<
Val
>::
eraseRightLink
() {
236
if
(
children_
[
static_cast
<
int
>(
BinTreeDir
::
RIGHT_CHILD
)]) {
237
children_
[
static_cast
<
int
>(
BinTreeDir
::
RIGHT_CHILD
)]->
parent_
=
nullptr
;
238
children_
[
static_cast
<
int
>(
BinTreeDir
::
RIGHT_CHILD
)]->
parent_dir_
239
=
BinTreeDir
::
NO_PARENT
;
240
children_
[
static_cast
<
int
>(
BinTreeDir
::
RIGHT_CHILD
)] =
nullptr
;
241
}
242
}
243
244
template
<
typename
Val
>
245
INLINE
void
BinTreeNode
<
Val
>::
eraseLink
(
BinTreeDir
tree_dir
) {
246
if
(
children_
[
static_cast
<
int
>(
tree_dir
)]) {
247
children_
[
static_cast
<
int
>(
tree_dir
)]->
parent_
=
nullptr
;
248
children_
[
static_cast
<
int
>(
tree_dir
)]->
parent_dir_
=
BinTreeDir
::
NO_PARENT
;
249
children_
[
static_cast
<
int
>(
tree_dir
)] =
nullptr
;
250
}
251
}
252
253
template
<
typename
Val
>
254
INLINE
BinTreeNode
<
Val
>*
BinTreeNode
<
Val
>::
leftmostNode
()
const
{
255
BinTreeNode
<
Val
>*
node
=
const_cast
<
BinTreeNode
<
Val
>* >(
this
);
256
257
while
(
node
->
children_
[
static_cast
<
int
>(
BinTreeDir
::
LEFT_CHILD
)])
258
node
=
node
->
children_
[
static_cast
<
int
>(
BinTreeDir
::
LEFT_CHILD
)];
259
260
return
node
;
261
}
262
263
template
<
typename
Val
>
264
INLINE
BinTreeNode
<
Val
>*
BinTreeNode
<
Val
>::
rightmostNode
()
const
{
265
BinTreeNode
<
Val
>*
node
=
const_cast
<
BinTreeNode
<
Val
>* >(
this
);
266
267
while
(
node
->
children_
[
static_cast
<
int
>(
BinTreeDir
::
RIGHT_CHILD
)])
268
node
=
node
->
children_
[
static_cast
<
int
>(
BinTreeDir
::
RIGHT_CHILD
)];
269
270
return
node
;
271
}
272
273
template
<
typename
Val
>
274
INLINE
BinTreeNode
<
Val
>*
BinTreeNode
<
Val
>::
root
()
const
{
275
BinTreeNode
<
Val
>*
node
=
const_cast
<
BinTreeNode
<
Val
>* >(
this
);
276
277
while
(
node
->
parent_
)
278
node
=
node
->
parent_
;
279
280
return
node
;
281
}
282
283
}
// namespace gum
284
285
#
endif
// DOXYGEN_SHOULD_SKIP_THIS
gum::Set::emplace
INLINE void emplace(Args &&... args)
Definition:
set_tpl.h:669