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),
48 right_child_(0), tree_(0), next_iter_(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_),
57 parent_(from.parent_), left_child_(from.left_child_),
58 right_child_(from.right_child_), tree_(from.tree_) {
59 GUM_CONS_CPY(BinSearchTreeIterator);
62 next_iter_ = tree_->iterator_list_;
63 tree_->iterator_list_ =
this;
68 template <
typename Val,
class Cmp,
class Node >
69 INLINE
void BinSearchTreeIterator< Val, Cmp, Node >::initialize_(
70 const BinSearchTree< Val, Cmp, Node >* tree,
71 const Node* current_node,
72 bool add_to_iterator_list) {
76 tree_ =
const_cast< BinSearchTree< Val, Cmp, Node >* >(tree);
77 node_ =
const_cast< Node* >(current_node);
79 if (add_to_iterator_list && tree_) {
80 next_iter_ = tree_->iterator_list_;
81 tree_->iterator_list_ =
this;
85 template <
typename Val,
class Cmp,
class Node >
86 INLINE
void BinSearchTreeIterator< Val, Cmp, Node >::detachFromTree_() {
88 BinSearchTreeIterator< Val, Cmp, Node >*iter, *prev_iter = 0;
90 for (iter = tree_->iterator_list_; iter !=
this && iter;
91 prev_iter = iter, iter = iter->next_iter_) {}
95 prev_iter->next_iter_ = next_iter_;
97 tree_->iterator_list_ = next_iter_;
102 template <
typename Val,
class Cmp,
class Node >
103 INLINE BinSearchTreeIterator< Val, Cmp, Node >::~BinSearchTreeIterator() {
104 GUM_DESTRUCTOR(BinSearchTreeIterator);
110 template <
typename Val,
class Cmp,
class Node >
111 INLINE
void BinSearchTreeIterator< Val, Cmp, Node >::clear() {
126 template <
typename Val,
class Cmp,
class Node >
127 INLINE BinSearchTreeIterator< Val, Cmp, Node >&
128 BinSearchTreeIterator< Val, Cmp, Node >::operator=(
129 const BinSearchTreeIterator< Val, Cmp, Node >& from) {
132 GUM_OP_CPY(BinSearchTreeIterator);
136 if (from.tree_ != tree_) {
141 next_iter_ = tree_->iterator_list_;
142 tree_->iterator_list_ =
this;
149 next_node_ = from.next_node_;
150 prev_node_ = from.prev_node_;
151 parent_ = from.parent_;
152 left_child_ = from.left_child_;
153 right_child_ = from.right_child_;
159 template <
typename Val,
class Cmp,
class Node >
160 INLINE
const Val& BinSearchTreeIterator< Val, Cmp, Node >::operator*()
const {
161 if (node_)
return node_->value();
163 GUM_ERROR(UndefinedIteratorValue,
164 "the iterator does not point to a node of the binary tree");
167 template <
typename Val,
class Cmp,
class Node >
168 INLINE Node* BinSearchTree< Val, Cmp, Node >::minNode_(Node* node)
const {
171 for (; node; prevNode = node, node = node->leftChild()) {}
176 template <
typename Val,
class Cmp,
class Node >
177 INLINE Node* BinSearchTree< Val, Cmp, Node >::maxNode_(Node* node)
const {
180 for (; node; prevNode = node, node = node->rightChild()) {}
185 template <
typename Val,
class Cmp,
class Node >
186 INLINE Node* BinSearchTree< Val, Cmp, Node >::succNode_(Node* node)
const {
189 if (node->rightChild())
return minNode_(node->rightChild());
191 Node* par = node->parent();
193 while (par && (node->parentDir() == BinTreeDir::RIGHT_CHILD)) {
201 template <
typename Val,
class Cmp,
class Node >
202 INLINE Node* BinSearchTree< Val, Cmp, Node >::prevNode_(Node* node)
const {
205 if (node->leftChild())
return maxNode_(node->leftChild());
207 Node* par = node->parent();
209 while (par && (node->parentDir() == BinTreeDir::LEFT_CHILD)) {
217 template <
typename Val,
class Cmp,
class Node >
218 INLINE BinSearchTreeIterator< Val, Cmp, Node >&
219 BinSearchTreeIterator< Val, Cmp, Node >::operator++() {
223 node_ = node_ ? tree_->succNode_(node_) : next_node_;
236 template <
typename Val,
class Cmp,
class Node >
237 INLINE BinSearchTreeIterator< Val, Cmp, Node >&
238 BinSearchTreeIterator< Val, Cmp, Node >::operator--() {
243 node_ = node_ ? tree_->prevNode_(node_) : prev_node_;
256 template <
typename Val,
class Cmp,
class Node >
257 INLINE
bool BinSearchTreeIterator< Val, Cmp, Node >::operator==(
258 const BinSearchTreeIterator< Val, Cmp, Node >& from)
const {
260 return (node_ == from.node_);
262 return ((node_ == from.node_) && (tree_ == from.tree_)
263 && (next_node_ == from.next_node_) && (prev_node_ == from.prev_node_)
264 && (parent_ == from.parent_) && (left_child_ == from.left_child_)
265 && (right_child_ == from.right_child_));
268 template <
typename Val,
class Cmp,
class Node >
269 INLINE
bool BinSearchTreeIterator< Val, Cmp, Node >::operator!=(
270 const BinSearchTreeIterator< Val, Cmp, Node >& from)
const {
272 return (node_ != from.node_);
274 return ((node_ != from.node_) || (tree_ != from.tree_)
275 || (next_node_ != from.next_node_) || (prev_node_ != from.prev_node_)
276 || (parent_ != from.parent_) || (left_child_ != from.left_child_)
277 || (right_child_ != from.right_child_));
280 template <
typename Val,
class Cmp,
class Node >
281 INLINE BinSearchTreeIterator< Val, Cmp, Node >&
282 BinSearchTreeIterator< Val, Cmp, Node >::up() {
286 node_ = node_ ? node_->parent() : parent_;
299 template <
typename Val,
class Cmp,
class Node >
300 INLINE BinSearchTreeIterator< Val, Cmp, Node >&
301 BinSearchTreeIterator< Val, Cmp, Node >::downLeft() {
305 node_ = node_ ? node_->leftChild() : left_child_;
318 template <
typename Val,
class Cmp,
class Node >
319 INLINE BinSearchTreeIterator< Val, Cmp, Node >&
320 BinSearchTreeIterator< Val, Cmp, Node >::downRight() {
324 node_ = node_ ? node_->rightChild() : right_child_;
343 template <
typename Val,
class Cmp,
class Node >
344 BinSearchTree< Val, Cmp, Node >::BinSearchTree(
bool uniqueness_policy) :
345 root_(0), iterator_list_(0), uniqueness_policy_(uniqueness_policy),
347 GUM_CONSTRUCTOR(BinSearchTree);
348 iter_end_.initialize_(
this, 0,
false);
351 template <
typename Val,
class Cmp,
class Node >
352 BinSearchTree< Val, Cmp, Node >::BinSearchTree(
353 const BinSearchTree< Val, Cmp, Node >& from) :
355 iterator_list_(0), uniqueness_policy_(from.uniqueness_policy_) {
357 GUM_CONS_CPY(BinSearchTree);
360 root_ = copy_(from.root_);
361 nb_elements_ = from.nb_elements_;
364 iter_end_.initialize_(
this, 0,
false);
367 template <
typename Val,
class Cmp,
class Node >
368 INLINE
void BinSearchTree< Val, Cmp, Node >::clear() {
370 for (iterator *iter = iterator_list_, *next_iter = 0; iter; iter = next_iter) {
371 next_iter = iter->next_iter_;
376 deleteSubTree_(root_);
384 template <
typename Val,
class Cmp,
class Node >
385 BinSearchTree< Val, Cmp, Node >& BinSearchTree< Val, Cmp, Node >::operator=(
386 const BinSearchTree< Val, Cmp, Node >& from) {
390 GUM_OP_CPY(BinSearchTree);
396 uniqueness_policy_ = from.uniqueness_policy_;
397 root_ = copy_(from.root_);
399 nb_elements_ = from.nb_elements_;
409 template <
typename Val,
class Cmp,
class Node >
410 BinSearchTree< Val, Cmp, Node >::~BinSearchTree() {
412 GUM_DESTRUCTOR(BinSearchTree);
418 template <
typename Val,
class Cmp,
class Node >
419 Node* BinSearchTree< Val, Cmp, Node >::copy_(Node* node,
426 Node* new_node =
new Node(*node);
428 if (parent) parent->insertChild(*new_node, dir);
431 copy_(node->leftChild(), new_node, BinTreeDir::LEFT_CHILD);
432 copy_(node->rightChild(), new_node, BinTreeDir::RIGHT_CHILD);
437 template <
typename Val,
class Cmp,
class Node >
438 void BinSearchTree< Val, Cmp, Node >::deleteSubTree_(Node* node) {
443 deleteSubTree_(node->leftChild());
444 deleteSubTree_(node->rightChild());
450 template <
typename Val,
class Cmp,
class Node >
451 INLINE Node* BinSearchTree< Val, Cmp, Node >::insert_(
const Val& val) {
458 if (cmp_(val, node->value()))
459 if (!node->leftChild()) {
462 return node->insertLeftChild(val);
464 node = node->leftChild();
466 else if (cmp_(node->value(), val) || !uniqueness_policy_)
467 if (!node->rightChild()) {
470 return node->insertRightChild(val);
472 node = node->rightChild();
477 GUM_ERROR(DuplicateElement,
478 "Val " << val <<
" already in the binary search tree");
484 root_ =
new Node(val);
489 template <
typename Val,
class Cmp,
class Node >
490 INLINE
const Val& BinSearchTree< Val, Cmp, Node >::insert(
const Val& val) {
491 return insert_(val)->value();
494 template <
typename Val,
class Cmp,
class Node >
495 INLINE
const Val& BinSearchTree< Val, Cmp, Node >::rootValue()
const {
497 GUM_ERROR(NotFound,
"no value in an empty Binary Search tree");
500 return root_->value();
503 template <
typename Val,
class Cmp,
class Node >
504 INLINE
const Val& BinSearchTree< Val, Cmp, Node >::minValue()
const {
506 GUM_ERROR(NotFound,
"no minimal value in an empty Binary Search tree");
509 return minNode_(root_)->value();
512 template <
typename Val,
class Cmp,
class Node >
513 INLINE
const Val& BinSearchTree< Val, Cmp, Node >::maxValue()
const {
515 GUM_ERROR(NotFound,
"no maximal value in an empty Binary Search tree");
518 return maxNode_(root_)->value();
521 template <
typename Val,
class Cmp,
class Node >
522 INLINE Node* BinSearchTree< Val, Cmp, Node >::getNode_(
const Val& val)
const {
529 if (cmp_(val, node->value())) {
530 if (!node->leftChild())
533 node = node->leftChild();
534 }
else if (cmp_(node->value(), val)) {
535 if (!node->rightChild())
538 node = node->rightChild();
547 template <
typename Val,
class Cmp,
class Node >
548 INLINE
bool BinSearchTree< Val, Cmp, Node >::contains(
const Val& val)
const {
549 return (getNode_(val) != 0);
552 template <
typename Val,
class Cmp,
class Node >
553 INLINE Size BinSearchTree< Val, Cmp, Node >::size()
const {
557 template <
typename Val,
class Cmp,
class Node >
558 INLINE
bool BinSearchTree< Val, Cmp, Node >::empty()
const {
559 return (nb_elements_ == 0);
562 template <
typename Val,
class Cmp,
class Node >
563 std::string BinSearchTree< Val, Cmp, Node >::toString()
const {
565 std::stringstream stream;
568 for (const_iterator iter = begin(); iter != end(); ++iter, deja =
true) {
569 if (deja) stream <<
" , ";
579 template <
typename Val,
class Cmp,
class Node >
580 INLINE
bool BinSearchTree< Val, Cmp, Node >::uniquenessPolicy()
const {
581 return uniqueness_policy_;
584 template <
typename Val,
class Cmp,
class Node >
586 BinSearchTree< Val, Cmp, Node >::setUniquenessPolicy(
const bool new_policy) {
587 uniqueness_policy_ = new_policy;
590 template <
typename Val,
class Cmp,
class Node >
591 INLINE BinSearchTreeIterator< Val, Cmp, Node >
592 BinSearchTree< Val, Cmp, Node >::begin() {
593 BinSearchTreeIterator< Val, Cmp, Node > iter;
594 iter.initialize_(
this, minNode_(root_),
true);
598 template <
typename Val,
class Cmp,
class Node >
599 INLINE BinSearchTreeIterator< Val, Cmp, Node >
600 BinSearchTree< Val, Cmp, Node >::begin()
const {
601 BinSearchTreeIterator< Val, Cmp, Node > iter;
602 iter.initialize_(
this, minNode_(root_),
true);
606 template <
typename Val,
class Cmp,
class Node >
607 INLINE BinSearchTreeIterator< Val, Cmp, Node >
608 BinSearchTree< Val, Cmp, Node >::rbegin() {
609 BinSearchTreeIterator< Val, Cmp, Node > iter;
610 iter.initialize_(
this, maxNode_(root_),
true);
614 template <
typename Val,
class Cmp,
class Node >
615 INLINE BinSearchTreeIterator< Val, Cmp, Node >
616 BinSearchTree< Val, Cmp, Node >::rbegin()
const {
617 BinSearchTreeIterator< Val, Cmp, Node > iter;
618 iter.initialize_(
this, maxNode_(root_),
true);
622 template <
typename Val,
class Cmp,
class Node >
623 INLINE
const BinSearchTreeIterator< Val, Cmp, Node >&
624 BinSearchTree< Val, Cmp, Node >::end() {
628 template <
typename Val,
class Cmp,
class Node >
629 INLINE
const BinSearchTreeIterator< Val, Cmp, Node >&
630 BinSearchTree< Val, Cmp, Node >::end()
const {
634 template <
typename Val,
class Cmp,
class Node >
635 INLINE
const BinSearchTreeIterator< Val, Cmp, Node >&
636 BinSearchTree< Val, Cmp, Node >::rend() {
640 template <
typename Val,
class Cmp,
class Node >
641 INLINE
const BinSearchTreeIterator< Val, Cmp, Node >&
642 BinSearchTree< Val, Cmp, Node >::rend()
const {
646 template <
typename Val,
class Cmp,
class Node >
647 INLINE BinSearchTreeIterator< Val, Cmp, Node >
648 BinSearchTree< Val, Cmp, Node >::root() {
649 BinSearchTreeIterator< Val, Cmp, Node > iter;
650 iter.initialize_(
this, root_,
true);
654 template <
typename Val,
class Cmp,
class Node >
655 INLINE BinSearchTreeIterator< Val, Cmp, Node >
656 BinSearchTree< Val, Cmp, Node >::root()
const {
657 BinSearchTreeIterator< Val, Cmp, Node > iter;
658 iter.initialize_(
this, root_,
true);
662 template <
typename Val,
class Cmp,
class Node >
663 void BinSearchTree< Val, Cmp, Node >::erase_(Node* node) {
668 updateEraseIterators__(node);
676 if (!node->leftChild() && !node->rightChild()) {
678 if (!node->parent()) root_ = 0;
685 else if (!node->leftChild()) {
687 if (!node->parent()) {
691 root_ = node->rightChild();
693 Node * parent = node->parent(), *child = node->rightChild();
694 BinTreeDir dir = node->parentDir();
695 parent->eraseLink(dir);
696 node->eraseRightLink();
697 parent->insertChild(*child, dir);
701 else if (!node->rightChild()) {
703 if (!node->parent()) {
707 root_ = node->leftChild();
709 Node * parent = node->parent(), *child = node->leftChild();
710 BinTreeDir dir = node->parentDir();
711 parent->eraseLink(dir);
712 node->eraseLeftLink();
713 parent->insertChild(*child, dir);
718 eraseWithTwoChildren__(node);
725 template <
typename Val,
class Cmp,
class Node >
726 INLINE
void BinSearchTree< Val, Cmp, Node >::eraseWithTwoChildren__(Node* node) {
741 Node* successor = succNode_(node);
743 if (successor == node->rightChild()) {
744 Node* left_child = node->leftChild();
745 node->eraseLeftLink();
746 node->eraseRightLink();
747 successor->insertLeftChild(*left_child);
749 if (!node->parent()) {
755 BinTreeDir par_dir = node->parentDir();
756 Node* parent = node->parent();
757 parent->eraseLink(par_dir);
758 parent->insertChild(*successor, par_dir);
761 Node* parent = successor->parent();
762 parent->eraseLeftLink();
764 if (successor->rightChild()) {
765 Node* succ_child = successor->rightChild();
766 successor->eraseRightLink();
767 parent->insertLeftChild(*succ_child);
770 Node *left = node->leftChild(), *right = node->rightChild();
771 node->eraseLeftLink();
772 node->eraseRightLink();
773 successor->insertLeftChild(*left);
774 successor->insertRightChild(*right);
776 if (!node->parent()) {
780 BinTreeDir par_dir = node->parentDir();
781 Node* parent = node->parent();
782 parent->eraseLink(par_dir);
783 parent->insertChild(*successor, par_dir);
788 template <
typename Val,
class Cmp,
class Node >
789 INLINE
void BinSearchTree< Val, Cmp, Node >::erase(
const Val& val) {
790 Node* n = getNode_(val);
793 GUM_ERROR(gum::NotFound,
"Value \"" << val <<
"\" not found");
798 template <
typename Val,
class Cmp,
class Node >
799 INLINE
void BinSearchTree< Val, Cmp, Node >::erase(
const iterator& iter) {
803 template <
typename Val,
class Cmp,
class Node >
804 void BinSearchTree< Val, Cmp, Node >::updateEraseIterators__(Node* node) {
805 for (iterator* iter = iterator_list_; iter; iter = iter->next_iter_) {
808 if (iter->node_ == node) {
810 iter->next_node_ = succNode_(node);
811 iter->prev_node_ = prevNode_(node);
812 iter->parent_ = node->parent();
813 iter->left_child_ = node->leftChild();
814 iter->right_child_ = node->rightChild();
815 }
else if (!iter->node_) {
816 if (iter->next_node_ == node) iter->next_node_ = succNode_(node);
818 if (iter->prev_node_ == node) iter->prev_node_ = prevNode_(node);
820 if (iter->parent_ == node) iter->parent_ = node->parent();
822 if (iter->left_child_ == node) iter->left_child_ = node->leftChild();
824 if (iter->right_child_ == node) iter->right_child_ = node->rightChild();