#pragma once #include namespace BinaryTree { template struct Node { T value; std::unique_ptr> left; std::unique_ptr> right; bool IsLeaf() const { return left == nullptr && right == nullptr; } Node(T const &_value) : value(_value), left(nullptr), right(nullptr) { } }; template class Tree { private: std::unique_ptr> root; std::unique_ptr> & GetRightMostLeaf(std::unique_ptr> &node) { std::unique_ptr> *nodePtr = &node; while ((*nodePtr)->right != nullptr) { nodePtr = &((*nodePtr)->right); } return *nodePtr; } void DeleteNode(std::unique_ptr> & node) { if(node == nullptr || node->IsLeaf()) { node.release(); } if(node->left == nullptr) { node = std::move(node->right); } if(node->right == nullptr) { node = std::move(node->left); } auto & replacementNode = GetRightMostLeaf(node); replacementNode->left.swap(node->left); replacementNode->right.swap(node->right); node.swap(replacementNode); replacementNode.release(); } std::unique_ptr> & FindNode(T const & value) { std::unique_ptr> *currentPtr = &root; while (*currentPtr != nullptr && (*currentPtr)->value != value) { if ((*currentPtr)->value > value) { currentPtr = &((*currentPtr)->left); } else { currentPtr = &((*currentPtr)->right); } } return *currentPtr; } public: void Insert(T const & value) { std::unique_ptr> *currentPtr = &root; while ((*currentPtr) != nullptr) { if ((*currentPtr)->value > value) { currentPtr = &((*currentPtr)->left); } else { currentPtr = &((*currentPtr)->right); } } *currentPtr = std::make_unique>(value); } void InsertNoDuplicates(T const & value) { auto & toInsertIn = FindNode(value); if(toInsertIn != nullptr) { return; } toInsertIn = std::make_unique>(value); } bool Contains(T const & value) { return FindNode(value) != nullptr; } void Delete(T const & value) { auto & node = FindNode(value); if (node == nullptr) { return; } DeleteNode(node); } Tree() : root(nullptr) {} }; } // namespace BinaryTree