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