32 #include <agrum/tools/core/binSearchTree.h> 33 #include <agrum/tools/core/exceptions.h> 35 #ifndef DOXYGEN_SHOULD_SKIP_THIS 45 template <
typename Val,
class Cmp,
class Node >
46 INLINE BinSearchTreeIterator< Val, Cmp, Node >::BinSearchTreeIterator() :
47 node_(0), next_node_(0), prev_node_(0), parent_(0), left_child_(0), right_child_(0), tree_(0),
49 GUM_CONSTRUCTOR(BinSearchTreeIterator);
52 template <
typename Val,
class Cmp,
class Node >
53 INLINE BinSearchTreeIterator< Val, Cmp, Node >::BinSearchTreeIterator(
54 const BinSearchTreeIterator< Val, Cmp, Node >& from) :
56 next_node_(from.next_node_), prev_node_(from.prev_node_), parent_(from.parent_),
57 left_child_(from.left_child_), right_child_(from.right_child_), tree_(from.tree_) {
58 GUM_CONS_CPY(BinSearchTreeIterator);
61 next_iter_ = tree_->iterator_list_;
62 tree_->iterator_list_ =
this;
67 template <
typename Val,
class Cmp,
class Node >
68 INLINE
void BinSearchTreeIterator< Val, Cmp, Node >::initialize_(
69 const BinSearchTree< Val, Cmp, Node >* tree,
70 const Node* current_node,
71 bool add_to_iterator_list) {
75 tree_ =
const_cast< BinSearchTree< Val, Cmp, Node >* >(tree);
76 node_ =
const_cast< Node* >(current_node);
78 if (add_to_iterator_list && tree_) {
79 next_iter_ = tree_->iterator_list_;
80 tree_->iterator_list_ =
this;
84 template <
typename Val,
class Cmp,
class Node >
85 INLINE
void BinSearchTreeIterator< Val, Cmp, Node >::detachFromTree_() {
87 BinSearchTreeIterator< Val, Cmp, Node >*iter, *prev_iter = 0;
89 for (iter = tree_->iterator_list_; iter !=
this && iter;
90 prev_iter = iter, iter = iter->next_iter_) {}
94 prev_iter->next_iter_ = next_iter_;
96 tree_->iterator_list_ = next_iter_;
101 template <
typename Val,
class Cmp,
class Node >
102 INLINE BinSearchTreeIterator< Val, Cmp, Node >::~BinSearchTreeIterator() {
103 GUM_DESTRUCTOR(BinSearchTreeIterator);
109 template <
typename Val,
class Cmp,
class Node >
110 INLINE
void BinSearchTreeIterator< Val, Cmp, Node >::clear() {
125 template <
typename Val,
class Cmp,
class Node >
126 INLINE BinSearchTreeIterator< Val, Cmp, Node >&
127 BinSearchTreeIterator< Val, Cmp, Node >::operator=(
128 const BinSearchTreeIterator< Val, Cmp, Node >& from) {
131 GUM_OP_CPY(BinSearchTreeIterator);
135 if (from.tree_ != tree_) {
140 next_iter_ = tree_->iterator_list_;
141 tree_->iterator_list_ =
this;
148 next_node_ = from.next_node_;
149 prev_node_ = from.prev_node_;
150 parent_ = from.parent_;
151 left_child_ = from.left_child_;
152 right_child_ = from.right_child_;
158 template <
typename Val,
class Cmp,
class Node >
159 INLINE
const Val& BinSearchTreeIterator< Val, Cmp, Node >::operator*()
const {
160 if (node_)
return node_->value();
162 GUM_ERROR(UndefinedIteratorValue,
"the iterator does not point to a node of the binary tree")
165 template <
typename Val,
class Cmp,
class Node >
166 INLINE Node* BinSearchTree< Val, Cmp, Node >::minNode_(Node* node)
const {
169 for (; node; prevNode = node, node = node->leftChild()) {}
174 template <
typename Val,
class Cmp,
class Node >
175 INLINE Node* BinSearchTree< Val, Cmp, Node >::maxNode_(Node* node)
const {
178 for (; node; prevNode = node, node = node->rightChild()) {}
183 template <
typename Val,
class Cmp,
class Node >
184 INLINE Node* BinSearchTree< Val, Cmp, Node >::succNode_(Node* node)
const {
187 if (node->rightChild())
return minNode_(node->rightChild());
189 Node* par = node->parent();
191 while (par && (node->parentDir() == BinTreeDir::RIGHT_CHILD)) {
199 template <
typename Val,
class Cmp,
class Node >
200 INLINE Node* BinSearchTree< Val, Cmp, Node >::prevNode_(Node* node)
const {
203 if (node->leftChild())
return maxNode_(node->leftChild());
205 Node* par = node->parent();
207 while (par && (node->parentDir() == BinTreeDir::LEFT_CHILD)) {
215 template <
typename Val,
class Cmp,
class Node >
216 INLINE BinSearchTreeIterator< Val, Cmp, Node >&
217 BinSearchTreeIterator< Val, Cmp, Node >::operator++() {
221 node_ = node_ ? tree_->succNode_(node_) : next_node_;
234 template <
typename Val,
class Cmp,
class Node >
235 INLINE BinSearchTreeIterator< Val, Cmp, Node >&
236 BinSearchTreeIterator< Val, Cmp, Node >::operator--() {
241 node_ = node_ ? tree_->prevNode_(node_) : prev_node_;
254 template <
typename Val,
class Cmp,
class Node >
255 INLINE
bool BinSearchTreeIterator< Val, Cmp, Node >::operator==(
256 const BinSearchTreeIterator< Val, Cmp, Node >& from)
const {
258 return (node_ == from.node_);
260 return ((node_ == from.node_) && (tree_ == from.tree_) && (next_node_ == from.next_node_)
261 && (prev_node_ == from.prev_node_) && (parent_ == from.parent_)
262 && (left_child_ == from.left_child_) && (right_child_ == from.right_child_));
265 template <
typename Val,
class Cmp,
class Node >
266 INLINE
bool BinSearchTreeIterator< Val, Cmp, Node >::operator!=(
267 const BinSearchTreeIterator< Val, Cmp, Node >& from)
const {
269 return (node_ != from.node_);
271 return ((node_ != from.node_) || (tree_ != from.tree_) || (next_node_ != from.next_node_)
272 || (prev_node_ != from.prev_node_) || (parent_ != from.parent_)
273 || (left_child_ != from.left_child_) || (right_child_ != from.right_child_));
276 template <
typename Val,
class Cmp,
class Node >
277 INLINE BinSearchTreeIterator< Val, Cmp, Node >& BinSearchTreeIterator< Val, Cmp, Node >::up() {
281 node_ = node_ ? node_->parent() : parent_;
294 template <
typename Val,
class Cmp,
class Node >
295 INLINE BinSearchTreeIterator< Val, Cmp, Node >&
296 BinSearchTreeIterator< Val, Cmp, Node >::downLeft() {
300 node_ = node_ ? node_->leftChild() : left_child_;
313 template <
typename Val,
class Cmp,
class Node >
314 INLINE BinSearchTreeIterator< Val, Cmp, Node >&
315 BinSearchTreeIterator< Val, Cmp, Node >::downRight() {
319 node_ = node_ ? node_->rightChild() : right_child_;
338 template <
typename Val,
class Cmp,
class Node >
339 BinSearchTree< Val, Cmp, Node >::BinSearchTree(
bool uniqueness_policy) :
340 root_(0), iterator_list_(0), uniqueness_policy_(uniqueness_policy), nb_elements_(0) {
341 GUM_CONSTRUCTOR(BinSearchTree);
342 iter_end_.initialize_(
this, 0,
false);
345 template <
typename Val,
class Cmp,
class Node >
346 BinSearchTree< Val, Cmp, Node >::BinSearchTree(
const BinSearchTree< Val, Cmp, Node >& from) :
347 root_(0), iterator_list_(0), uniqueness_policy_(from.uniqueness_policy_) {
349 GUM_CONS_CPY(BinSearchTree);
352 root_ = copy_(from.root_);
353 nb_elements_ = from.nb_elements_;
356 iter_end_.initialize_(
this, 0,
false);
359 template <
typename Val,
class Cmp,
class Node >
360 INLINE
void BinSearchTree< Val, Cmp, Node >::clear() {
362 for (iterator *iter = iterator_list_, *next_iter = 0; iter; iter = next_iter) {
363 next_iter = iter->next_iter_;
368 deleteSubTree_(root_);
376 template <
typename Val,
class Cmp,
class Node >
377 BinSearchTree< Val, Cmp, Node >&
378 BinSearchTree< Val, Cmp, Node >::operator=(
const BinSearchTree< Val, Cmp, Node >& from) {
382 GUM_OP_CPY(BinSearchTree);
388 uniqueness_policy_ = from.uniqueness_policy_;
389 root_ = copy_(from.root_);
391 nb_elements_ = from.nb_elements_;
401 template <
typename Val,
class Cmp,
class Node >
402 BinSearchTree< Val, Cmp, Node >::~BinSearchTree() {
404 GUM_DESTRUCTOR(BinSearchTree);
410 template <
typename Val,
class Cmp,
class Node >
411 Node* BinSearchTree< Val, Cmp, Node >::copy_(Node* node, Node* parent, BinTreeDir dir) {
416 Node* new_node =
new Node(*node);
418 if (parent) parent->insertChild(*new_node, dir);
421 copy_(node->leftChild(), new_node, BinTreeDir::LEFT_CHILD);
422 copy_(node->rightChild(), new_node, BinTreeDir::RIGHT_CHILD);
427 template <
typename Val,
class Cmp,
class Node >
428 void BinSearchTree< Val, Cmp, Node >::deleteSubTree_(Node* node) {
433 deleteSubTree_(node->leftChild());
434 deleteSubTree_(node->rightChild());
440 template <
typename Val,
class Cmp,
class Node >
441 INLINE Node* BinSearchTree< Val, Cmp, Node >::insert_(
const Val& val) {
448 if (cmp_(val, node->value()))
449 if (!node->leftChild()) {
452 return node->insertLeftChild(val);
454 node = node->leftChild();
456 else if (cmp_(node->value(), val) || !uniqueness_policy_)
457 if (!node->rightChild()) {
460 return node->insertRightChild(val);
462 node = node->rightChild();
467 GUM_ERROR(DuplicateElement,
"Val " << val <<
" already in the binary search tree")
473 root_ =
new Node(val);
478 template <
typename Val,
class Cmp,
class Node >
479 INLINE
const Val& BinSearchTree< Val, Cmp, Node >::insert(
const Val& val) {
480 return insert_(val)->value();
483 template <
typename Val,
class Cmp,
class Node >
484 INLINE
const Val& BinSearchTree< Val, Cmp, Node >::rootValue()
const {
485 if (root_ == 0) { GUM_ERROR(NotFound,
"no value in an empty Binary Search tree") }
487 return root_->value();
490 template <
typename Val,
class Cmp,
class Node >
491 INLINE
const Val& BinSearchTree< Val, Cmp, Node >::minValue()
const {
492 if (root_ == 0) { GUM_ERROR(NotFound,
"no minimal value in an empty Binary Search tree") }
494 return minNode_(root_)->value();
497 template <
typename Val,
class Cmp,
class Node >
498 INLINE
const Val& BinSearchTree< Val, Cmp, Node >::maxValue()
const {
499 if (root_ == 0) { GUM_ERROR(NotFound,
"no maximal value in an empty Binary Search tree") }
501 return maxNode_(root_)->value();
504 template <
typename Val,
class Cmp,
class Node >
505 INLINE Node* BinSearchTree< Val, Cmp, Node >::getNode_(
const Val& val)
const {
512 if (cmp_(val, node->value())) {
513 if (!node->leftChild())
516 node = node->leftChild();
517 }
else if (cmp_(node->value(), val)) {
518 if (!node->rightChild())
521 node = node->rightChild();
530 template <
typename Val,
class Cmp,
class Node >
531 INLINE
bool BinSearchTree< Val, Cmp, Node >::contains(
const Val& val)
const {
532 return (getNode_(val) != 0);
535 template <
typename Val,
class Cmp,
class Node >
536 INLINE Size BinSearchTree< Val, Cmp, Node >::size()
const {
540 template <
typename Val,
class Cmp,
class Node >
541 INLINE
bool BinSearchTree< Val, Cmp, Node >::empty()
const {
542 return (nb_elements_ == 0);
545 template <
typename Val,
class Cmp,
class Node >
546 std::string BinSearchTree< Val, Cmp, Node >::toString()
const {
548 std::stringstream stream;
551 for (const_iterator iter = begin(); iter != end(); ++iter, deja =
true) {
552 if (deja) stream <<
" , ";
562 template <
typename Val,
class Cmp,
class Node >
563 INLINE
bool BinSearchTree< Val, Cmp, Node >::uniquenessPolicy()
const {
564 return uniqueness_policy_;
567 template <
typename Val,
class Cmp,
class Node >
568 INLINE
void BinSearchTree< Val, Cmp, Node >::setUniquenessPolicy(
const bool new_policy) {
569 uniqueness_policy_ = new_policy;
572 template <
typename Val,
class Cmp,
class Node >
573 INLINE BinSearchTreeIterator< Val, Cmp, Node > BinSearchTree< Val, Cmp, Node >::begin() {
574 BinSearchTreeIterator< Val, Cmp, Node > iter;
575 iter.initialize_(
this, minNode_(root_),
true);
579 template <
typename Val,
class Cmp,
class Node >
580 INLINE BinSearchTreeIterator< Val, Cmp, Node > BinSearchTree< Val, Cmp, Node >::begin()
const {
581 BinSearchTreeIterator< Val, Cmp, Node > iter;
582 iter.initialize_(
this, minNode_(root_),
true);
586 template <
typename Val,
class Cmp,
class Node >
587 INLINE BinSearchTreeIterator< Val, Cmp, Node > BinSearchTree< Val, Cmp, Node >::rbegin() {
588 BinSearchTreeIterator< Val, Cmp, Node > iter;
589 iter.initialize_(
this, maxNode_(root_),
true);
593 template <
typename Val,
class Cmp,
class Node >
594 INLINE BinSearchTreeIterator< Val, Cmp, Node > BinSearchTree< Val, Cmp, Node >::rbegin()
const {
595 BinSearchTreeIterator< Val, Cmp, Node > iter;
596 iter.initialize_(
this, maxNode_(root_),
true);
600 template <
typename Val,
class Cmp,
class Node >
601 INLINE
const BinSearchTreeIterator< Val, Cmp, Node >& BinSearchTree< Val, Cmp, Node >::end() {
605 template <
typename Val,
class Cmp,
class Node >
606 INLINE
const BinSearchTreeIterator< Val, Cmp, Node >&
607 BinSearchTree< Val, Cmp, Node >::end()
const {
611 template <
typename Val,
class Cmp,
class Node >
612 INLINE
const BinSearchTreeIterator< Val, Cmp, Node >& BinSearchTree< Val, Cmp, Node >::rend() {
616 template <
typename Val,
class Cmp,
class Node >
617 INLINE
const BinSearchTreeIterator< Val, Cmp, Node >&
618 BinSearchTree< Val, Cmp, Node >::rend()
const {
622 template <
typename Val,
class Cmp,
class Node >
623 INLINE BinSearchTreeIterator< Val, Cmp, Node > BinSearchTree< Val, Cmp, Node >::root() {
624 BinSearchTreeIterator< Val, Cmp, Node > iter;
625 iter.initialize_(
this, root_,
true);
629 template <
typename Val,
class Cmp,
class Node >
630 INLINE BinSearchTreeIterator< Val, Cmp, Node > BinSearchTree< Val, Cmp, Node >::root()
const {
631 BinSearchTreeIterator< Val, Cmp, Node > iter;
632 iter.initialize_(
this, root_,
true);
636 template <
typename Val,
class Cmp,
class Node >
637 void BinSearchTree< Val, Cmp, Node >::erase_(Node* node) {
642 _updateEraseIterators_(node);
650 if (!node->leftChild() && !node->rightChild()) {
652 if (!node->parent()) root_ = 0;
659 else if (!node->leftChild()) {
661 if (!node->parent()) {
665 root_ = node->rightChild();
667 Node * parent = node->parent(), *child = node->rightChild();
668 BinTreeDir dir = node->parentDir();
669 parent->eraseLink(dir);
670 node->eraseRightLink();
671 parent->insertChild(*child, dir);
675 else if (!node->rightChild()) {
677 if (!node->parent()) {
681 root_ = node->leftChild();
683 Node * parent = node->parent(), *child = node->leftChild();
684 BinTreeDir dir = node->parentDir();
685 parent->eraseLink(dir);
686 node->eraseLeftLink();
687 parent->insertChild(*child, dir);
692 _eraseWithTwoChildren_(node);
699 template <
typename Val,
class Cmp,
class Node >
700 INLINE
void BinSearchTree< Val, Cmp, Node >::_eraseWithTwoChildren_(Node* node) {
715 Node* successor = succNode_(node);
717 if (successor == node->rightChild()) {
718 Node* left_child = node->leftChild();
719 node->eraseLeftLink();
720 node->eraseRightLink();
721 successor->insertLeftChild(*left_child);
723 if (!node->parent()) {
729 BinTreeDir par_dir = node->parentDir();
730 Node* parent = node->parent();
731 parent->eraseLink(par_dir);
732 parent->insertChild(*successor, par_dir);
735 Node* parent = successor->parent();
736 parent->eraseLeftLink();
738 if (successor->rightChild()) {
739 Node* succ_child = successor->rightChild();
740 successor->eraseRightLink();
741 parent->insertLeftChild(*succ_child);
744 Node *left = node->leftChild(), *right = node->rightChild();
745 node->eraseLeftLink();
746 node->eraseRightLink();
747 successor->insertLeftChild(*left);
748 successor->insertRightChild(*right);
750 if (!node->parent()) {
754 BinTreeDir par_dir = node->parentDir();
755 Node* parent = node->parent();
756 parent->eraseLink(par_dir);
757 parent->insertChild(*successor, par_dir);
762 template <
typename Val,
class Cmp,
class Node >
763 INLINE
void BinSearchTree< Val, Cmp, Node >::erase(
const Val& val) {
764 Node* n = getNode_(val);
766 if (n ==
nullptr) GUM_ERROR(gum::NotFound,
"Value \"" << val <<
"\" not found")
771 template <
typename Val,
class Cmp,
class Node >
772 INLINE
void BinSearchTree< Val, Cmp, Node >::erase(
const iterator& iter) {
776 template <
typename Val,
class Cmp,
class Node >
777 void BinSearchTree< Val, Cmp, Node >::_updateEraseIterators_(Node* node) {
778 for (iterator* iter = iterator_list_; iter; iter = iter->next_iter_) {
781 if (iter->node_ == node) {
783 iter->next_node_ = succNode_(node);
784 iter->prev_node_ = prevNode_(node);
785 iter->parent_ = node->parent();
786 iter->left_child_ = node->leftChild();
787 iter->right_child_ = node->rightChild();
788 }
else if (!iter->node_) {
789 if (iter->next_node_ == node) iter->next_node_ = succNode_(node);
791 if (iter->prev_node_ == node) iter->prev_node_ = prevNode_(node);
793 if (iter->parent_ == node) iter->parent_ = node->parent();
795 if (iter->left_child_ == node) iter->left_child_ = node->leftChild();
797 if (iter->right_child_ == node) iter->right_child_ = node->rightChild();