#include #include #include #include #include /** * Binary Search Tree implementation with smart pointers * Template class supporting any comparable type */ template class BinarySearchTree { private: struct Node { T data; std::unique_ptr left; std::unique_ptr right; Node(const T& value) : data(value), left(nullptr), right(nullptr) {} }; std::unique_ptr root; size_t size_; void insertHelper(std::unique_ptr& node, const T& value) { if (!node) { node = std::make_unique(value); ++size_; return; } if (value < node->data) { insertHelper(node->left, value); } else if (value > node->data) { insertHelper(node->right, value); } // Ignore duplicates } bool searchHelper(const std::unique_ptr& node, const T& value) const { if (!node) return false; if (value == node->data) return true; else if (value < node->data) return searchHelper(node->left, value); else return searchHelper(node->right, value); } void inorderHelper(const std::unique_ptr& node, std::vector& result) const { if (!node) return; inorderHelper(node->left, result); result.push_back(node->data); inorderHelper(node->right, result); } std::unique_ptr removeHelper(std::unique_ptr node, const T& value) { if (!node) return nullptr; if (value < node->data) { node->left = removeHelper(std::move(node->left), value); } else if (value > node->data) { node->right = removeHelper(std::move(node->right), value); } else { // Node to delete found --size_; if (!node->left) return std::move(node->right); if (!node->right) return std::move(node->left); // Node has two children Node* successor = findMin(node->right.get()); node->data = successor->data; node->right = removeHelper(std::move(node->right), successor->data); ++size_; // Compensate for decrement in recursive call } return node; } Node* findMin(Node* node) const { while (node->left) { node = node->left.get(); } return node; } public: BinarySearchTree() : root(nullptr), size_(0) {} void insert(const T& value) { insertHelper(root, value); } bool search(const T& value) const { return searchHelper(root, value); } void remove(const T& value) { root = removeHelper(std::move(root), value); } std::vector inorderTraversal() const { std::vector result; inorderHelper(root, result); return result; } size_t size() const { return size_; } bool empty() const { return size_ == 0; } void clear() { root.reset(); size_ = 0; } }; /** * Dynamic Array implementation with automatic resizing */ template class DynamicArray { private: std::unique_ptr data; size_t capacity_; size_t size_; void resize() { size_t newCapacity = capacity_ == 0 ? 1 : capacity_ * 2; auto newData = std::make_unique(newCapacity); for (size_t i = 0; i < size_; ++i) { newData[i] = std::move(data[i]); } data = std::move(newData); capacity_ = newCapacity; } public: DynamicArray() : data(nullptr), capacity_(0), size_(0) {} explicit DynamicArray(size_t initialCapacity) : data(std::make_unique(initialCapacity)), capacity_(initialCapacity), size_(0) {} void pushBack(const T& value) { if (size_ >= capacity_) { resize(); } data[size_++] = value; } void pushBack(T&& value) { if (size_ >= capacity_) { resize(); } data[size_++] = std::move(value); } T& operator[](size_t index) { if (index >= size_) { throw std::out_of_range("Index out of bounds"); } return data[index]; } const T& operator[](size_t index) const { if (index >= size_) { throw std::out_of_range("Index out of bounds"); } return data[index]; } void popBack() { if (size_ > 0) { --size_; } } size_t size() const { return size_; } size_t capacity() const { return capacity_; } bool empty() const { return size_ == 0; } void clear() { size_ = 0; } // Iterator support T* begin() { return data.get(); } T* end() { return data.get() + size_; } const T* begin() const { return data.get(); } const T* end() const { return data.get() + size_; } }; /** * Stack implementation using dynamic array */ template class Stack { private: DynamicArray container; public: void push(const T& value) { container.pushBack(value); } void push(T&& value) { container.pushBack(std::move(value)); } void pop() { if (empty()) { throw std::runtime_error("Stack underflow"); } container.popBack(); } T& top() { if (empty()) { throw std::runtime_error("Stack is empty"); } return container[container.size() - 1]; } const T& top() const { if (empty()) { throw std::runtime_error("Stack is empty"); } return container[container.size() - 1]; } bool empty() const { return container.empty(); } size_t size() const { return container.size(); } }; // Demonstration and testing int main() { std::cout << "=== Binary Search Tree Demo ===" << std::endl; BinarySearchTree bst; std::vector values = {50, 30, 70, 20, 40, 60, 80, 10, 25, 35}; for (int val : values) { bst.insert(val); } std::cout << "Tree size: " << bst.size() << std::endl; std::cout << "Inorder traversal: "; auto inorder = bst.inorderTraversal(); for (size_t i = 0; i < inorder.size(); ++i) { std::cout << inorder[i]; if (i < inorder.size() - 1) std::cout << ", "; } std::cout << std::endl; std::cout << "\n=== Dynamic Array Demo ===" << std::endl; DynamicArray arr; arr.pushBack("Hello"); arr.pushBack("World"); arr.pushBack("C++"); arr.pushBack("Templates"); std::cout << "Array contents: "; for (size_t i = 0; i < arr.size(); ++i) { std::cout << arr[i]; if (i < arr.size() - 1) std::cout << ", "; } std::cout << std::endl; std::cout << "\n=== Stack Demo ===" << std::endl; Stack stack; for (int i = 1; i <= 5; ++i) { stack.push(i * 10); } std::cout << "Stack contents (top to bottom): "; while (!stack.empty()) { std::cout << stack.top() << " "; stack.pop(); } std::cout << std::endl; return 0; }