56#ifndef DOXYGEN_SHOULD_SKIP_THIS
66 template <
typename Val,
class Cmp,
class Node >
68 node_(nullptr), next_node_(nullptr), prev_node_(nullptr), parent_(nullptr),
69 left_child_(nullptr), right_child_(nullptr), tree_(nullptr), next_iter_(nullptr) {
70 GUM_CONSTRUCTOR(BinSearchTreeIterator);
73 template <
typename Val,
class Cmp,
class Node >
74 INLINE BinSearchTreeIterator< Val, Cmp, Node >::BinSearchTreeIterator(
76 node_(from.node_), next_node_(from.next_node_), prev_node_(from.prev_node_),
77 parent_(from.parent_), left_child_(from.left_child_), right_child_(from.right_child_),
79 GUM_CONS_CPY(BinSearchTreeIterator);
81 if (tree_ !=
nullptr) {
82 next_iter_ = tree_->iterator_list_;
83 tree_->iterator_list_ =
this;
84 }
else next_iter_ =
nullptr;
87 template <
typename Val,
class Cmp,
class Node >
88 INLINE
void BinSearchTreeIterator< Val, Cmp, Node >::initialize_(
89 const BinSearchTree< Val, Cmp, Node >* tree,
90 const Node* current_node,
91 bool add_to_iterator_list) {
95 tree_ =
const_cast< BinSearchTree< Val, Cmp, Node >*
>(tree);
96 node_ =
const_cast< Node*
>(current_node);
98 if (add_to_iterator_list && (tree_ !=
nullptr)) {
99 next_iter_ = tree_->iterator_list_;
100 tree_->iterator_list_ =
this;
104 template <
typename Val,
class Cmp,
class Node >
105 INLINE
void BinSearchTreeIterator< Val, Cmp, Node >::detachFromTree_() {
106 if (tree_ !=
nullptr) {
107 BinSearchTreeIterator< Val, Cmp, Node >*iter, *prev_iter =
nullptr;
109 for (iter = tree_->iterator_list_; iter !=
this && iter !=
nullptr;
110 prev_iter = iter, iter = iter->next_iter_) {}
112 if (iter !=
nullptr) {
113 if (prev_iter !=
nullptr) prev_iter->next_iter_ = next_iter_;
114 else tree_->iterator_list_ = next_iter_;
119 template <
typename Val,
class Cmp,
class Node >
120 INLINE BinSearchTreeIterator< Val, Cmp, Node >::~BinSearchTreeIterator() {
121 GUM_DESTRUCTOR(BinSearchTreeIterator);
127 template <
typename Val,
class Cmp,
class Node >
128 INLINE
void BinSearchTreeIterator< Val, Cmp, Node >::clear() {
134 next_node_ =
nullptr;
135 prev_node_ =
nullptr;
137 left_child_ =
nullptr;
138 right_child_ =
nullptr;
140 next_iter_ =
nullptr;
143 template <
typename Val,
class Cmp,
class Node >
145 BinSearchTreeIterator< Val, Cmp, Node >::operator=(
149 GUM_OP_CPY(BinSearchTreeIterator);
153 if (from.tree_ != tree_) {
157 if (tree_ !=
nullptr) {
158 next_iter_ = tree_->iterator_list_;
159 tree_->iterator_list_ =
this;
160 }
else next_iter_ =
nullptr;
165 next_node_ = from.next_node_;
166 prev_node_ = from.prev_node_;
167 parent_ = from.parent_;
168 left_child_ = from.left_child_;
169 right_child_ = from.right_child_;
175 template <
typename Val,
class Cmp,
class Node >
176 INLINE
const Val& BinSearchTreeIterator< Val, Cmp, Node >::operator*()
const {
177 if (node_ !=
nullptr)
return node_->value();
179 GUM_ERROR(UndefinedIteratorValue,
"the iterator does not point to a node of the binary tree")
182 template <
typename Val,
class Cmp,
class Node >
183 INLINE Node* BinSearchTree< Val, Cmp, Node >::minNode_(Node* node)
const {
184 Node* prevNode =
nullptr;
186 for (; node !=
nullptr; prevNode = node, node = node->leftChild()) {}
191 template <
typename Val,
class Cmp,
class Node >
192 INLINE Node* BinSearchTree< Val, Cmp, Node >::maxNode_(Node* node)
const {
193 Node* prevNode =
nullptr;
195 for (; node !=
nullptr; prevNode = node, node = node->rightChild()) {}
200 template <
typename Val,
class Cmp,
class Node >
201 INLINE Node* BinSearchTree< Val, Cmp, Node >::succNode_(Node* node)
const {
202 if (node ==
nullptr)
return nullptr;
204 if (node->rightChild())
return minNode_(node->rightChild());
206 Node* par = node->parent();
208 while ((par !=
nullptr) && (node->parentDir() == BinTreeDir::RIGHT_CHILD)) {
216 template <
typename Val,
class Cmp,
class Node >
217 INLINE Node* BinSearchTree< Val, Cmp, Node >::prevNode_(Node* node)
const {
218 if (node ==
nullptr)
return nullptr;
220 if (node->leftChild())
return maxNode_(node->leftChild());
222 Node* par = node->parent();
224 while ((par !=
nullptr) && (node->parentDir() == BinTreeDir::LEFT_CHILD)) {
232 template <
typename Val,
class Cmp,
class Node >
234 BinSearchTreeIterator< Val, Cmp, Node >::operator++() {
238 node_ = node_ !=
nullptr ? tree_->succNode_(node_) : next_node_;
240 if (node_ ==
nullptr) {
241 next_node_ =
nullptr;
242 prev_node_ =
nullptr;
244 left_child_ =
nullptr;
245 right_child_ =
nullptr;
251 template <
typename Val,
class Cmp,
class Node >
253 BinSearchTreeIterator< Val, Cmp, Node >::operator--() {
258 node_ = node_ !=
nullptr ? tree_->prevNode_(node_) : prev_node_;
260 if (node_ ==
nullptr) {
261 next_node_ =
nullptr;
262 prev_node_ =
nullptr;
264 left_child_ =
nullptr;
265 right_child_ =
nullptr;
271 template <
typename Val,
class Cmp,
class Node >
272 INLINE
bool BinSearchTreeIterator< Val, Cmp, Node >::operator==(
274 if (node_ !=
nullptr)
return (node_ == from.node_);
276 return ((node_ == from.node_) && (tree_ == from.tree_) && (next_node_ == from.next_node_)
277 && (prev_node_ == from.prev_node_) && (parent_ == from.parent_)
278 && (left_child_ == from.left_child_) && (right_child_ == from.right_child_));
281 template <
typename Val,
class Cmp,
class Node >
282 INLINE
bool BinSearchTreeIterator< Val, Cmp, Node >::operator!=(
284 if (node_ !=
nullptr)
return (node_ != from.node_);
286 return ((node_ != from.node_) || (tree_ != from.tree_) || (next_node_ != from.next_node_)
287 || (prev_node_ != from.prev_node_) || (parent_ != from.parent_)
288 || (left_child_ != from.left_child_) || (right_child_ != from.right_child_));
291 template <
typename Val,
class Cmp,
class Node >
296 node_ = node_ !=
nullptr ? node_->parent() : parent_;
298 if (node_ ==
nullptr) {
299 next_node_ =
nullptr;
300 prev_node_ =
nullptr;
302 left_child_ =
nullptr;
303 right_child_ =
nullptr;
309 template <
typename Val,
class Cmp,
class Node >
311 BinSearchTreeIterator< Val, Cmp, Node >::downLeft() {
315 node_ = node_ !=
nullptr ? node_->leftChild() : left_child_;
317 if (node_ ==
nullptr) {
318 next_node_ =
nullptr;
319 prev_node_ =
nullptr;
321 left_child_ =
nullptr;
322 right_child_ =
nullptr;
328 template <
typename Val,
class Cmp,
class Node >
330 BinSearchTreeIterator< Val, Cmp, Node >::downRight() {
334 node_ = node_ !=
nullptr ? node_->rightChild() : right_child_;
336 if (node_ ==
nullptr) {
337 next_node_ =
nullptr;
338 prev_node_ =
nullptr;
340 left_child_ =
nullptr;
341 right_child_ =
nullptr;
353 template <
typename Val,
class Cmp,
class Node >
354 BinSearchTree< Val, Cmp, Node >::BinSearchTree(
bool uniqueness_policy) :
355 root_(nullptr), iterator_list_(nullptr), uniqueness_policy_(uniqueness_policy),
357 GUM_CONSTRUCTOR(BinSearchTree);
358 iter_end_.initialize_(
this,
nullptr,
false);
361 template <
typename Val,
class Cmp,
class Node >
362 BinSearchTree< Val, Cmp, Node >::BinSearchTree(
const BinSearchTree< Val, Cmp, Node >& from) :
363 root_(nullptr), iterator_list_(nullptr), uniqueness_policy_(from.uniqueness_policy_) {
365 GUM_CONS_CPY(BinSearchTree);
368 root_ = copy_(from.root_);
369 nb_elements_ = from.nb_elements_;
372 iter_end_.initialize_(
this,
nullptr,
false);
375 template <
typename Val,
class Cmp,
class Node >
376 INLINE
void BinSearchTree< Val, Cmp, Node >::clear() {
378 for (iterator *iter = iterator_list_, *next_iter =
nullptr; iter; iter = next_iter) {
379 next_iter = iter->next_iter_;
384 deleteSubTree_(root_);
392 template <
typename Val,
class Cmp,
class Node >
393 BinSearchTree< Val, Cmp, Node >&
394 BinSearchTree< Val, Cmp, Node >::operator=(
const BinSearchTree< Val, Cmp, Node >& from) {
398 GUM_OP_CPY(BinSearchTree);
404 uniqueness_policy_ = from.uniqueness_policy_;
405 root_ = copy_(from.root_);
407 nb_elements_ = from.nb_elements_;
417 template <
typename Val,
class Cmp,
class Node >
418 BinSearchTree< Val, Cmp, Node >::~BinSearchTree() {
420 GUM_DESTRUCTOR(BinSearchTree);
426 template <
typename Val,
class Cmp,
class Node >
427 Node* BinSearchTree< Val, Cmp, Node >::copy_(Node* node, Node* parent, BinTreeDir dir) {
429 if (!node)
return nullptr;
432 Node* new_node =
new Node(*node);
434 if (parent) parent->insertChild(*new_node, dir);
437 copy_(node->leftChild(), new_node, BinTreeDir::LEFT_CHILD);
438 copy_(node->rightChild(), new_node, BinTreeDir::RIGHT_CHILD);
443 template <
typename Val,
class Cmp,
class Node >
444 void BinSearchTree< Val, Cmp, Node >::deleteSubTree_(Node* node) {
449 deleteSubTree_(node->leftChild());
450 deleteSubTree_(node->rightChild());
456 template <
typename Val,
class Cmp,
class Node >
457 INLINE Node* BinSearchTree< Val, Cmp, Node >::insert_(
const Val& val) {
464 if (cmp_(val, node->value()))
465 if (!node->leftChild()) {
468 return node->insertLeftChild(val);
470 node = node->leftChild();
472 else if (cmp_(node->value(), val) || !uniqueness_policy_)
473 if (!node->rightChild()) {
476 return node->insertRightChild(val);
478 node = node->rightChild();
489 root_ =
new Node(val);
494 template <
typename Val,
class Cmp,
class Node >
495 INLINE
const Val& BinSearchTree< Val, Cmp, Node >::insert(
const Val& val) {
496 return insert_(val)->value();
499 template <
typename Val,
class Cmp,
class Node >
500 INLINE
const Val& BinSearchTree< Val, Cmp, Node >::rootValue()
const {
501 if (root_ ==
nullptr) {
GUM_ERROR(
NotFound,
"no value in an empty Binary Search tree") }
503 return root_->value();
506 template <
typename Val,
class Cmp,
class Node >
507 INLINE
const Val& BinSearchTree< Val, Cmp, Node >::minValue()
const {
508 if (root_ ==
nullptr) {
GUM_ERROR(
NotFound,
"no minimal value in an empty Binary Search tree") }
510 return minNode_(root_)->value();
513 template <
typename Val,
class Cmp,
class Node >
514 INLINE
const Val& BinSearchTree< Val, Cmp, Node >::maxValue()
const {
515 if (root_ ==
nullptr) {
GUM_ERROR(
NotFound,
"no maximal value in an empty Binary Search tree") }
517 return maxNode_(root_)->value();
520 template <
typename Val,
class Cmp,
class Node >
521 INLINE Node* BinSearchTree< Val, Cmp, Node >::getNode_(
const Val& val)
const {
528 if (cmp_(val, node->value())) {
529 if (!node->leftChild())
return nullptr;
530 else node = node->leftChild();
531 }
else if (cmp_(node->value(), val)) {
532 if (!node->rightChild())
return nullptr;
533 else node = node->rightChild();
541 template <
typename Val,
class Cmp,
class Node >
542 INLINE
bool BinSearchTree< Val, Cmp, Node >::contains(
const Val& val)
const {
543 return (getNode_(val) !=
nullptr);
546 template <
typename Val,
class Cmp,
class Node >
547 INLINE Size BinSearchTree< Val, Cmp, Node >::size()
const {
551 template <
typename Val,
class Cmp,
class Node >
552 INLINE
bool BinSearchTree< Val, Cmp, Node >::empty()
const {
553 return (nb_elements_ == 0);
556 template <
typename Val,
class Cmp,
class Node >
557 std::string BinSearchTree< Val, Cmp, Node >::toString()
const {
559 std::stringstream stream;
562 for (const_iterator iter = begin(); iter != end(); ++iter, deja =
true) {
563 if (deja) stream <<
" , ";
573 template <
typename Val,
class Cmp,
class Node >
574 INLINE
bool BinSearchTree< Val, Cmp, Node >::uniquenessPolicy()
const {
575 return uniqueness_policy_;
578 template <
typename Val,
class Cmp,
class Node >
579 INLINE
void BinSearchTree< Val, Cmp, Node >::setUniquenessPolicy(
const bool new_policy) {
580 uniqueness_policy_ = new_policy;
583 template <
typename Val,
class Cmp,
class Node >
586 iter.initialize_(
this, minNode_(root_),
true);
590 template <
typename Val,
class Cmp,
class Node >
593 iter.initialize_(
this, minNode_(root_),
true);
597 template <
typename Val,
class Cmp,
class Node >
600 iter.initialize_(
this, maxNode_(root_),
true);
604 template <
typename Val,
class Cmp,
class Node >
607 iter.initialize_(
this, maxNode_(root_),
true);
611 template <
typename Val,
class Cmp,
class Node >
616 template <
typename Val,
class Cmp,
class Node >
618 BinSearchTree< Val, Cmp, Node >::end()
const {
622 template <
typename Val,
class Cmp,
class Node >
627 template <
typename Val,
class Cmp,
class Node >
629 BinSearchTree< Val, Cmp, Node >::rend()
const {
633 template <
typename Val,
class Cmp,
class Node >
636 iter.initialize_(
this, root_,
true);
640 template <
typename Val,
class Cmp,
class Node >
643 iter.initialize_(
this, root_,
true);
647 template <
typename Val,
class Cmp,
class Node >
648 void BinSearchTree< Val, Cmp, Node >::erase_(Node* node) {
653 _updateEraseIterators_(node);
661 if (!node->leftChild() && !node->rightChild()) {
663 if (!node->parent()) root_ =
nullptr;
670 else if (!node->leftChild()) {
672 if (!node->parent()) {
676 root_ = node->rightChild();
678 Node * parent = node->parent(), *child = node->rightChild();
679 BinTreeDir dir = node->parentDir();
680 parent->eraseLink(dir);
681 node->eraseRightLink();
682 parent->insertChild(*child, dir);
686 else if (!node->rightChild()) {
688 if (!node->parent()) {
692 root_ = node->leftChild();
694 Node * parent = node->parent(), *child = node->leftChild();
695 BinTreeDir dir = node->parentDir();
696 parent->eraseLink(dir);
697 node->eraseLeftLink();
698 parent->insertChild(*child, dir);
703 _eraseWithTwoChildren_(node);
710 template <
typename Val,
class Cmp,
class Node >
711 INLINE
void BinSearchTree< Val, Cmp, Node >::_eraseWithTwoChildren_(Node* node) {
726 Node* successor = succNode_(node);
728 if (successor == node->rightChild()) {
729 Node* left_child = node->leftChild();
730 node->eraseLeftLink();
731 node->eraseRightLink();
732 successor->insertLeftChild(*left_child);
734 if (!node->parent()) {
740 BinTreeDir par_dir = node->parentDir();
741 Node* parent = node->parent();
742 parent->eraseLink(par_dir);
743 parent->insertChild(*successor, par_dir);
746 Node* parent = successor->parent();
747 parent->eraseLeftLink();
749 if (successor->rightChild()) {
750 Node* succ_child = successor->rightChild();
751 successor->eraseRightLink();
752 parent->insertLeftChild(*succ_child);
755 Node *left = node->leftChild(), *right = node->rightChild();
756 node->eraseLeftLink();
757 node->eraseRightLink();
758 successor->insertLeftChild(*left);
759 successor->insertRightChild(*right);
761 if (!node->parent()) {
765 BinTreeDir par_dir = node->parentDir();
766 Node* parent = node->parent();
767 parent->eraseLink(par_dir);
768 parent->insertChild(*successor, par_dir);
773 template <
typename Val,
class Cmp,
class Node >
774 INLINE
void BinSearchTree< Val, Cmp, Node >::erase(
const Val& val) {
775 Node* n = getNode_(val);
777 if (n ==
nullptr)
GUM_ERROR(gum::NotFound,
"Value \"" << val <<
"\" not found")
782 template < typename Val, class
Cmp, class Node >
783 INLINE
void BinSearchTree< Val,
Cmp, Node >::erase(const iterator& iter) {
787 template <
typename Val,
class Cmp,
class Node >
788 void BinSearchTree< Val, Cmp, Node >::_updateEraseIterators_(Node* node) {
789 for (iterator* iter = iterator_list_; iter; iter = iter->next_iter_) {
792 if (iter->node_ == node) {
793 iter->node_ =
nullptr;
794 iter->next_node_ = succNode_(node);
795 iter->prev_node_ = prevNode_(node);
796 iter->parent_ = node->parent();
797 iter->left_child_ = node->leftChild();
798 iter->right_child_ = node->rightChild();
799 }
else if (!iter->node_) {
800 if (iter->next_node_ == node) iter->next_node_ = succNode_(node);
802 if (iter->prev_node_ == node) iter->prev_node_ = prevNode_(node);
804 if (iter->parent_ == node) iter->parent_ = node->parent();
806 if (iter->left_child_ == node) iter->left_child_ = node->leftChild();
808 if (iter->right_child_ == node) iter->right_child_ = node->rightChild();
Basic binary search trees.
BinSearchTreeIterator()
Class Constructors and Destructors.
Exception : a similar element already exists.
Exception : the element we looked for cannot be found.
#define GUM_ERROR(type, msg)
gum is the global namespace for all aGrUM entities