I am new to C++ and am attempting to write the following binary search tree using the iterator pattern (and std::optional
in C++17):
#include <memory>
#include <optional>
#include <stack>
template <typename T>
class BinarySearchTree {
public:
BinarySearchTree(T key)
: key_(key),
left_(nullptr),
right_(nullptr) {}
BinarySearchTree(const BinarySearchTree& bst) {
key_ = bst.key_;
left_ = std::make_unique<BinarySearchTree>(*bst.left_);
right_ = std::make_unique<BinarySearchTree>(*bst.right_);
}
void insert(T key);
T key() { return key_; }
std::unique_ptr<BinarySearchTree> left() { return std::make_unique<BinarySearchTree>(*left_); }
std::unique_ptr<BinarySearchTree> right() { return std::make_unique<BinarySearchTree>(*right_); }
private:
T key_;
std::unique_ptr<BinarySearchTree> left_;
std::unique_ptr<BinarySearchTree> right_;
};
template <typename T>
void BinarySearchTree<T>::insert(T key) {
auto insert = [key](auto& node) {
if (node) {
node->insert(key);
} else {
node = std::make_unique<BinarySearchTree>(key);
}
};
if (key <= key_) {
insert(left_);
} else {
insert(right_);
}
}
template <typename T>
class BinarySearchTreeIterator {
public:
BinarySearchTreeIterator(BinarySearchTree<T>& bst, bool forward)
: bst_(std::make_unique<BinarySearchTree<T>>(bst)),
forward_(forward) {}
std::optional<T> operator*() { return current_; }
void operator++() {
while (bst_ || !stack_.empty()) {
if (bst_) {
stack_.emplace(std::make_unique<BinarySearchTree<T>>(*bst_));
bst_ = std::make_unique<BinarySearchTree<T>>(*(forward_ ? bst_->left() : bst_->right()));
} else {
bst_ = std::make_unique<BinarySearchTree<T>>(*(stack_.top()));
stack_.pop();
current_ = bst_->key();
bst_ = std::make_unique<BinarySearchTree<T>>(*(forward_ ? bst_->right() : bst_->left()));
break;
}
}
}
private:
std::unique_ptr<BinarySearchTree<T>> bst_;
bool forward_;
std::stack<std::unique_ptr<BinarySearchTree<T>>> stack_;
std::optional<T> current_;
};
I am not sure if my usage of std::unique_ptr
is correct or idiomatic.