aGrUM 2.3.2
a C++ library for (probabilistic) graphical models
splay_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-2025 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-2025 *
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#pragma once
41
42
50
51namespace gum {
52 /* =========================================================================*/
53 /* =========================================================================*/
54 /* === Implementation of gumSplayBinaryNode === */
55 /* =========================================================================*/
56 /* =========================================================================*/
57
58 // a function used to perform copies of HashTableLists
59
60 template < class Element >
61 INLINE void
63 HashTable< Element, SplayBinaryNode< Element >* >& addr) {
64 if (addr.exists(from.elt)) addr[from.elt] = this;
65 else addr.insert(from.elt, this);
66
67 elt = from.elt;
68
69 size = from.size;
70
71 pere = 0;
72
73 if (from.fg) {
74 fg = new SplayBinaryNode< Element >(*from.fg, addr);
75 fg->pere = this;
76 } else {
77 fg = 0;
78 }
79
80 if (from.fd) {
81 fd = new SplayBinaryNode< Element >(*from.fd, addr);
82 fd->pere = this;
83 } else {
84 fd = 0;
85 }
86 }
87
88 // constructor
89
90 template < class Element >
92 const Element& e,
93 HashTable< Element, SplayBinaryNode< Element >* >& addr,
96 SplayBinaryNode* p) : elt(e), size(1), fg(g), fd(d), pere(p) {
97 if (addr.exists(elt)) addr[elt] = this;
98 else addr.insert(elt, this);
99
100 // for debugging purposes
101 GUM_CONSTRUCTOR(SplayBinaryNode);
102 }
103
104 // copy operator
105
106 template < class Element >
108 const SplayBinaryNode< Element >& from,
109 HashTable< Element, SplayBinaryNode< Element >* >& addr) {
110 copy_(from, addr);
111 // for debugging purposes
112 GUM_CONSTRUCTOR(SplayBinaryNode);
113 }
114
115 // destructor
116
117 template < class Element >
119 // for debugging purposes
120 GUM_DESTRUCTOR(SplayBinaryNode);
121 // remove the subtrees
122
123 if (fg) delete fg;
124
125 if (fd) delete fd;
126 }
127
128 // Perform a right rotation, returns the node
129
130 template < class Element >
132 Size size_;
133 // Must be called on a node with a father
134 GUM_ASSERT(pere != 0);
135 // We chain childs
136 pere->fg = fd;
137
138 if (fd) fd->pere = pere;
139
140 fd = pere;
141
143
144 fd->pere = this;
145
146 // We compute the size of rigth child
147 size_ = 1;
148
149 if (fd->fg) size_ += fd->fg->size;
150
151 if (fd->fd) size_ += fd->fd->size;
152
153 fd->size = size_;
154
155 // size_ == fd->size
156 if (fg) size_ += fg->size;
157
158 ++size_;
159
160 size = size_;
161
162 // We chain father
163 pere = p;
164
165 if (pere) {
166 if (pere->fg == fd) {
167 // I'm left child of my father
168 pere->fg = this;
169 } else {
170 // I'm right child of my father
171 GUM_ASSERT(pere->fd == fd);
172 pere->fd = this;
173 }
174 }
175
176 return this;
177 }
178
179 // Perform a left rotation, returns the node
180
181 template < class Element >
183 Size size_;
184 // Must be call on a node with a father
185 GUM_ASSERT(pere != 0);
186 // We chain childs
187 pere->fd = fg;
188
189 if (fg) fg->pere = pere;
190
191 fg = pere;
192
194
195 fg->pere = this;
196
197 // We compute the size of rigth child
198 size_ = 1;
199
200 if (fg->fg) size_ += fg->fg->size;
201
202 if (fg->fd) size_ += fg->fd->size;
203
204 fg->size = size_;
205
206 if (fd) size_ += fd->size;
207
208 ++size_;
209
210 size = size_;
211
212 // We chain father
213 pere = p;
214
215 if (pere) {
216 if (pere->fg == fg) {
217 // I'm left child of my father
218 pere->fg = this;
219 } else {
220 // I'm right child of my father
221 GUM_ASSERT(pere->fd == fg);
222 pere->fd = this;
223 }
224 }
225
226 return this;
227 }
228
229 // Perform a splay rotation, the node return is the root
230
231 template < class Element >
234
235 while (pere) {
236 // While this node isn't the root
237 gdp = pere->pere; // gdp can be nullptr
238
239 if (!gdp) {
240 if (this == pere->fg) {
241 // I'm the left child of my father
242 return zig();
243 } else {
244 GUM_ASSERT(this == pere->fd);
245 // I'm the right child of my father
246 return zag();
247 }
248 } else {
249 if (this == pere->fg) {
250 // I'm the left child of my father
251 if (pere == gdp->fg) {
252 gdp->fg = zig();
253 } else {
254 GUM_ASSERT(pere == gdp->fd);
255 gdp->fd = zig();
256 }
257 } else {
258 GUM_ASSERT(this == pere->fd);
259 // I'm the right child of my father
260
261 if (pere == gdp->fg) {
262 gdp->fg = zag();
263 } else {
264 GUM_ASSERT(pere == gdp->fd);
265 gdp->fd = zag();
266 }
267 }
268 }
269 }
270
271 return this; // for compiler satisfaction
272 }
273
274 // Concatenation of two threes
275
276 template < class Element >
279 HashTable< Element, SplayBinaryNode< Element >* >& addr) {
281 GUM_ASSERT(b != 0);
282 SplayBinaryNode< Element >* act = this;
283
284 for (; act->fd; act = act->fd)
285 ;
286
287 // act is the rightmost element
288 act->splay();
289
290 // insertion
291 act->fd = b;
292
293 b->pere = act;
294
295 act->size = 1;
296
297 if (act->fg) act->size += act->fg->size;
298
299 act->size += act->fd->size;
300
301 return act;
302 }
303
304 // Get the position of the node
305
306 template < class Element >
308 if (!pere) {
309 // I'm the root
310 if (fg) return fg->size + 1;
311 else return 0;
312 } else if (pere->fg == this) {
313 // I'm the left child of my father
314 int pos = pere->position() - 1;
315
316 if (fd) pos -= fd->size;
317
318 return pos;
319 } else {
320 // I'm the right child of my father
321 int pos = pere->position() + 1;
322
323 if (fg) pos += fg->size;
324
325 return pos;
326 }
327 }
328
329 // Get the element in the node
330
331 template < class Element >
332 INLINE const Element& SplayBinaryNode< Element >::getElement() const {
333 return elt;
334 }
335
336 /*
337 * @return the left child
338 * @warning the returned value can be null
339 */
340
341 template < class Element >
343 return fg;
344 }
345
346 /*
347 * @return the right child
348 * @warning the returned value can be null
349 */
350
351 template < class Element >
353 return fd;
354 }
355
356 /* =========================================================================*/
357 /* =========================================================================*/
358 /* === Implementation of SplayTree === */
359 /* =========================================================================*/
360 /* =========================================================================*/
361
362 // a function used to perform copies
363
364 template < class Element >
366 if (from.root) {
368 } else {
369 root = 0;
370 }
371 }
372
373 // basic constructor, make an empty splay tree
374
375 template < class Element >
377 // for debugging purposes
378 GUM_CONSTRUCTOR(SplayTree);
379 }
380
381 // basic constructor, make a splay tree with one element
382 /*
383 * @param e the element of the tree
384 */
385
386 template < class Element >
387 INLINE SplayTree< Element >::SplayTree(const Element& e) : root(0), addr() {
389 // for debugging purposes
390 GUM_CONSTRUCTOR(SplayTree);
391 }
392
393 // copy constructor
394
395 template < class Element >
397 copy_(from);
398 // for debugging purposes
399 GUM_CONS_CPY(SplayTree);
400 }
401
402 // Assignment operator
403
404 template < class Element >
406 // avoid self assignment
407 if (this != &from) {
408 // for debugging purposes
409 GUM_OP_CPY(SplayTree);
410 // delete the old contents
411
412 if (root) delete root;
413
414 addr.clear();
415
416 copy_(from);
417 }
418
419 return *this;
420 }
421
422 // Destructor
423
424 template < class Element >
426 // for debugging purposes
427 GUM_DESTRUCTOR(SplayTree);
428
429 if (root) delete (root);
430 }
431
432 // Get the element at the position n
433
434 template < class Element >
435 Element& SplayTree< Element >::operator[](const unsigned int i) {
436 int val = i;
437
438 if (!root) {
439 GUM_ERROR(NotFound, "The tree is empty !")
440 } else if (val >= root->size) {
441 GUM_ERROR(NotFound, "The index is too large !")
442 } else {
443 // The element exists
444 // Find it
446 int pos_act = val - 1;
447 bool next = true;
448
449 while (next) {
450 if (!act->fg) pos_act = 0;
451 else pos_act = act->fg->size;
452
453 if (pos_act > val) {
454 act = act->fg;
455 } else if (pos_act < val) {
456 act = act->fd;
457 val -= (pos_act + 1);
458 } else {
459 next = false;
460 }
461 }
462
463 root = act->splay();
464
465 return root->elt;
466 }
467 }
468
469 template < class Element >
470 const Element& SplayTree< Element >::operator[](const unsigned int i) const {
471 int val = i;
472
473 if (!root) {
474 GUM_ERROR(NotFound, "The tree is empty !")
475 } else if (val >= root->size) {
476 GUM_ERROR(NotFound, "The index is too large !")
477 } else {
478 // The element exists
479 // Find it
481 int pos_act = val - 1;
482 bool next = true;
483
484 while (next) {
485 if (!act->fg) pos_act = 0;
486 else pos_act = act->fg->size;
487
488 if (pos_act > val) {
489 act = act->fg;
490 } else if (pos_act < val) {
491 act = act->fd;
492 val -= (pos_act + 1);
493 } else {
494 next = false;
495 }
496 }
497
498 root = act->splay();
499
500 return root->elt;
501 }
502 }
503
504 // Get the first element
505
506 template < class Element >
507 INLINE Element& SplayTree< Element >::front() {
509
510 if (!root) { GUM_ERROR(NotFound, "The splay tree is empty") }
511
512 if (act->fg)
513 for (; act->fg; act = act->fg)
514 ;
515
516 root = act->splay();
517
518 return root->elt;
519 }
520
521 // Get the last element
522
523 template < class Element >
524 INLINE Element& SplayTree< Element >::back() {
526
527 if (!root) { GUM_ERROR(NotFound, "The splay tree is empty") }
528
529 if (act->fd)
530 for (; act->fd; act = act->fd)
531 ;
532
533 root = act->splay();
534
535 return root->elt;
536 }
537
538 // Remove the first element
539
540 template < class Element >
543
544 if (root) {
545 if (root->fg)
546 for (; act->fg; act = act->fg)
547 ;
548
549 act = act->splay();
550
551 root = act->fd;
552
553 if (root) root->pere = 0;
554
555 act->fd = 0;
556
557 delete act;
558 }
559 }
560
561 // Remove the last element
562
563 template < class Element >
566
567 if (root) {
568 if (root->fd)
569 for (; act->fd; act = act->fd)
570 ;
571
572 act = act->splay();
573
574 root = act->fg;
575
576 if (root) root->pere = 0;
577
578 act->fg = 0;
579
580 delete act;
581 }
582 }
583
584 // Add an element in the first position
585
586 template < class Element >
587 INLINE void SplayTree< Element >::pushFront(const Element& e) {
589
590 if (root) {
591 if (root->fg)
592 for (; act->fg; act = act->fg)
593 ;
594
595 root = act->splay();
596
597 root->fg = new SplayBinaryNode< Element >(e, addr, 0, 0, root);
598 } else {
600 }
601 }
602
603 // Add an element in the last position
604
605 template < class Element >
606 INLINE void SplayTree< Element >::pushBack(const Element& e) {
608
609 if (root) {
610 if (root->fd)
611 for (; act->fd; act = act->fd)
612 ;
613
614 root = act->splay();
615
616 root->fd = new SplayBinaryNode< Element >(e, addr, 0, 0, root);
617 } else {
619 }
620 }
621
622 // Add an element to the tree
623
624 template < class Element >
625 INLINE void SplayTree< Element >::insert(const Element& e) {
627
628 if (!root) {
630 } else {
631 while (act->fd) {
632 ++act->size;
633 act = act->fd;
634 }
635
636 // act->fd == nullptr
637 act->fd = new SplayBinaryNode< Element >(e, addr, 0, 0, act);
638
639 ++act->size;
640
641 root = act->fd->splay();
642 }
643 }
644
645 // Concatenation of two trees
646 /*
647 * @param s the tree to add
648 */
649
650 template < class Element >
652 if (s.root) {
653 if (root) {
654 root = root->join(s.root, addr);
655 } else {
657 }
658 }
659 }
660
661 // removeInfo removes all the information about the nodes contains by e
662
663 template < class Element >
664 INLINE static void removeInfo(const SplayBinaryNode< Element >* e,
665 HashTable< Element, SplayBinaryNode< Element >* >& addr) {
666 GUM_ASSERT(addr.exists(e->getElement()));
667 addr.erase(e->getElement());
668
669 if (e->getFg()) removeInfo(e->getFg(), addr);
670
671 if (e->getFd()) removeInfo(e->getFd(), addr);
672 }
673
674 // Split the tree at the element
675
676 template < class Element >
678 GUM_ASSERT(i >= 0 && i < root->size);
679 GUM_ASSERT(root != 0);
680
681 if (i == 0) {
682 // the tree will be empty
683 // the returned tree is a copy of the present tree
684 SplayTree< Element > s = *this;
685 addr.clear();
686 delete root;
687 root = 0;
688 return s;
689 } else if (i == root->size - 1) {
691 return s;
692 } else {
693 // We will find the node at position i
695 int pos = root->position();
696
697 while (pos != i) {
698 GUM_ASSERT(act != 0);
699
700 if (i < pos) {
701 act = act->fg;
702 } else {
703 act = act->fd;
704 }
705
706 pos = act->position();
707 }
708
709 // We reorganize the tree
710 act->splay();
711
712 // We take the first part
713 root = act->fg;
714
715 if (root) root->pere = 0;
716
717 // We take the second part
719
720 s.root = act;
721
722 s.root->fg = 0;
723
724 Size size_ = 1;
725
726 if (s.root->fd) size_ += s.root->fd->size;
727
728 s.root->size = size_;
729
730 // We remove the old nodes in the hash table
731 // Complexity O(n) => very expensive
732 removeInfo(act, addr);
733
734 return s;
735 }
736 }
737
738 // Split the tree at the element
739
740 template < typename Element >
742 GUM_ASSERT(root != 0);
743
744 if (!addr.exists(e)) { GUM_ERROR(NotFound, "not enough elements in the splay tree") }
745
746 // We will find the node at position i
748
749 // We reorganize the tree
750 act->splay();
751
752 // We take the two parts
754
755 s.root = act->fd;
756
757 if (s.root) { s.root->pere = 0; }
758
759 root = act->fg;
760
761 if (root) root->pere = 0;
762
763 act->fg = 0;
764
765 // We remove the old nodes in the hash table
766 // Complexity O(n) => very expensive
767 removeInfo(act, addr);
768
769 act->fd = 0;
770
771 delete act;
772
773 return s;
774 }
775
776 // The number of elements in the tree
777
778 template < class Element >
780 if (root) return root->size;
781 else return Size(0);
782 }
783
784 // Test if the tree contains the element
785
786 template < class Element >
787 INLINE bool SplayTree< Element >::contains(const Element& e) const {
788 return addr.exists(e);
789 }
790
791 // Display the node
792
793 template < typename Element >
794 std::ostream& operator<<(std::ostream& out, const SplayBinaryNode< Element >& e) {
795 if (e.fg) out << *e.fg << ",";
796
797 out << e.elt;
798
799 if (e.fd) out << "," << *e.fd;
800
801 return out;
802 }
803
804 // Display the tree
805
806 template < typename Element >
807 INLINE std::ostream& operator<<(std::ostream& out, const SplayTree< Element >& s) {
808 out << "|[";
809
810 if (s.root) out << *s.root;
811
812 out << "]|";
813
814 return out;
815 }
816
817} /* namespace gum */
The class for generic Hash Tables.
Definition hashTable.h:637
Exception : the element we looked for cannot be found.
the nodes of splay trees
Definition splay.h:91
SplayBinaryNode * fg
The left child.
Definition splay.h:214
SplayBinaryNode< Element > * zag()
A left rotation, the node must hava a father.
Definition splay_tpl.h:182
const Element & getElement() const
Returns the element in the node.
Definition splay_tpl.h:332
SplayBinaryNode(const Element &e, HashTable< Element, SplayBinaryNode< Element > * > &addr, SplayBinaryNode *g=0, SplayBinaryNode *d=0, SplayBinaryNode *p=0)
Basic constructor: creates a node with a reference to the element.
Definition splay_tpl.h:91
int position() const
Position of the node.
Definition splay_tpl.h:307
SplayBinaryNode * pere
The father, nullptr for the root.
Definition splay.h:220
void copy_(const SplayBinaryNode< Element > &from, HashTable< Element, SplayBinaryNode< Element > * > &addr)
A function used to perform copies.
Definition splay_tpl.h:62
SplayBinaryNode * fd
The right child.
Definition splay.h:217
const SplayBinaryNode< Element > * getFg() const
Returns the left child.
Definition splay_tpl.h:342
~SplayBinaryNode()
Class destructor.
Definition splay_tpl.h:118
Element elt
The content.
Definition splay.h:208
SplayBinaryNode< Element > * join(const SplayBinaryNode< Element > *e, HashTable< Element, SplayBinaryNode< Element > * > &addr)
Concatenation of two trees.
Definition splay_tpl.h:278
SplayBinaryNode< Element > * splay()
A splay rotation, the node will be the root of the tree.
Definition splay_tpl.h:232
const SplayBinaryNode< Element > * getFd() const
Returns the right child.
Definition splay_tpl.h:352
SplayBinaryNode< Element > * zig()
A right rotation, the node must have a father.
Definition splay_tpl.h:131
Size size
The size of the sub-tree.
Definition splay.h:211
Element & operator[](const unsigned int i)
Get the element at the position n.
Definition splay_tpl.h:435
Element & front()
Get the first element.
Definition splay_tpl.h:507
~SplayTree()
Class destructor.
Definition splay_tpl.h:425
void pushFront(const Element &e)
Add an element in the first position.
Definition splay_tpl.h:587
bool contains(const Element &e) const
Test if the tree contains the element.
Definition splay_tpl.h:787
SplayBinaryNode< Element > * root
Root of the tree.
Definition splay.h:434
SplayTree()
Basic constructor, make an empty splay tree.
Definition splay_tpl.h:376
void popBack()
Remove the last element.
Definition splay_tpl.h:564
void popFront()
Remove the first element.
Definition splay_tpl.h:541
Size size() const
The number of elements in the tree.
Definition splay_tpl.h:779
SplayTree< Element > & operator=(const SplayTree< Element > &from)
Assignment operator.
Definition splay_tpl.h:405
Element & back()
Get the last element.
Definition splay_tpl.h:524
void join(const SplayTree< Element > &s)
Concatenation of two trees.
Definition splay_tpl.h:651
HashTable< Element, SplayBinaryNode< Element > * > addr
The hash table to find quickly the position of a node.
Definition splay.h:437
SplayTree< Element > split(const int i)
Divide the tree at the position.
Definition splay_tpl.h:677
void copy_(const SplayTree< Element > &)
a function used to perform copies
Definition splay_tpl.h:365
void insert(const Element &e)
Add an element to the tree.
Definition splay_tpl.h:625
void pushBack(const Element &e)
Add an element in the last position.
Definition splay_tpl.h:606
SplayTree< Element > split_by_val(const Element &e)
Divide the tree at the position.
Definition splay_tpl.h:741
#define GUM_ERROR(type, msg)
Definition exceptions.h:72
std::size_t Size
In aGrUM, hashed values are unsigned long int.
Definition types.h:74
gum is the global namespace for all aGrUM entities
Definition agrum.h:46
std::ostream & operator<<(std::ostream &stream, const AVLTree< Val, Cmp > &tree)
display the content of a tree
Definition AVLTree.h:913
static INLINE void removeInfo(const SplayBinaryNode< Element > *e, HashTable< Element, SplayBinaryNode< Element > * > &addr)
Definition splay_tpl.h:664
Splay Trees header file.