#ifndef BST_H
#define BST_H
#include <vector>
#include <stdexcept>
using namespace std;
template<typename T>
class TreeNode
{
public:
T element;
TreeNode<T>* left;
TreeNode<T>* right;
TreeNode(T element)
{
this->element = element;
left = nullptr;
right = nullptr;
}
};
template <typename T>
class Iterator: public std::iterator<std::forward_iterator_tag, T>
{
public:
Iterator(TreeNode<T>* p)
{
if (p == nullptr)
current = -1;
else
{
treeToVector(p);
current = 0;
}
}
Iterator operator++()
{
current++;
if (current == v.size())
current = -1;
return *this;
}
T &operator*()
{
return v[current];
}
bool operator==(const Iterator<T>& iterator) const
{
return current == iterator.current;
}
bool operator!=(const Iterator<T>& iterator) const
{
return current != iterator.current;
}
private:
int current;
vector<T> v;
void treeToVector(const TreeNode<T>* p)
{
if (p != nullptr)
{
treeToVector(p->left);
v.push_back(p->element);
treeToVector(p->right);
}
}
};
template <typename T>
class BST
{
public:
BST();
BST(T elements[], int arraySize);
BST(const BST<T>& tree);
~BST();
bool search(T element) const;
virtual bool insert(T element);
virtual bool remove(T element);
void inorder() const;
void preorder() const;
void postorder() const;
int getSize() const;
void clear();
vector<TreeNode<T>*>* path(T element) const;
Iterator<T> begin() const
{
return Iterator<T>(root);
};
Iterator<T> end() const
{
return Iterator<T>(nullptr);
};
protected:
TreeNode<T>* root;
int size;
virtual TreeNode<T>* createNewNode(T element);
private:
void inorder(const TreeNode<T>* root) const;
void postorder(const TreeNode<T>* root) const;
void preorder(const TreeNode<T>* root) const;
void copy(const TreeNode<T>* root);
void clear(const TreeNode<T>* root);
};
template <typename T>
BST<T>::BST()
{
root = nullptr;
size = 0;
}
template <typename T>
BST<T>::BST(T elements[], int arraySize)
{
root = nullptr;
size = 0;
for (int i = 0; i < arraySize; i++)
{
insert(elements[i]);
}
}
template <typename T>
BST<T>::BST(const BST<T>& tree)
{
root = nullptr;
size = 0;
copy(tree.root);
}
template <typename T>
void BST<T>::copy(const TreeNode<T>* root)
{
if (root != nullptr)
{
insert(root->element);
copy(root->left);
copy(root->right);
}
}
template <typename T>
BST<T>::~BST()
{
clear();
}
template <typename T>
bool BST<T>::search(T element) const
{
TreeNode<T>* current = root;
while (current != nullptr)
if (element < current->element)
{
current = current->left;
}
else if (element > current->element)
{
current = current->right;
}
else
return true;
return false;
}
template <typename T>
TreeNode<T>* BST<T>::createNewNode(T element)
{
return new TreeNode<T>(element);
}
template <typename T>
bool BST<T>::insert(T element)
{
if (root == nullptr)
root = createNewNode(element);
else
{
TreeNode<T>* parent = nullptr;
TreeNode<T>* current = root;
while (current != nullptr)
if (element < current->element)
{
parent = current;
current = current->left;
}
else if (element > current->element)
{
parent = current;
current = current->right;
}
else
return false;
if (element < parent->element)
parent->left = createNewNode(element);
else
parent->right = createNewNode(element);
}
size++;
return true;
}
template <typename T>
void BST<T>::inorder() const
{
inorder(root);
}
template <typename T>
void BST<T>::inorder(const TreeNode<T>* root) const
{
if (root == nullptr) return;
inorder(root->left);
cout << root->element << " ";
inorder(root->right);
}
template <typename T>
void BST<T>::postorder() const
{
postorder(root);
}
template <typename T>
void BST<T>::postorder(const TreeNode<T>* root) const
{
if (root == nullptr) return;
postorder(root->left);
postorder(root->right);
cout << root->element << " ";
}
template <typename T>
void BST<T>::preorder() const
{
preorder(root);
}
template <typename T>
void BST<T>::preorder(const TreeNode<T>* root) const
{
if (root == nullptr) return;
cout << root->element << " ";
preorder(root->left);
preorder(root->right);
}
template <typename T>
int BST<T>::getSize() const
{
return size;
}
template <typename T>
void BST<T>::clear()
{
}
template <typename T>
vector<TreeNode<T>*>* BST<T>::path(T element) const
{
vector<TreeNode<T>*>* v = new vector<TreeNode<T>*>();
TreeNode<T>* current = root;
while (current != nullptr)
{
v->push_back(current);
if (element < current->element)
current = current->left;
else if (element > current->element)
current = current->right;
else
break;
}
return v;
}
template <typename T>
bool BST<T>::remove(T element)
{
TreeNode<T>* parent = nullptr;
TreeNode<T>* current = root;
while (current != nullptr)
{
if (element < current->element)
{
parent = current;
current = current->left;
}
else if (element > current->element)
{
parent = current;
current = current->right;
}
else
break;
}
if (current == nullptr)
return false;
if (current->left == nullptr)
{
if (parent == nullptr)
{
root = current->right;
}
else
{
if (element < parent->element)
parent->left = current->right;
else
parent->right = current->right;
}
delete current;
}
else
{
TreeNode<T>* parentOfRightMost = current;
TreeNode<T>* rightMost = current->left;
while (rightMost->right != nullptr)
{
parentOfRightMost = rightMost;
rightMost = rightMost->right;
}
current->element = rightMost->element;
if (parentOfRightMost->right == rightMost)
parentOfRightMost->right = rightMost->left;
else
parentOfRightMost->left = rightMost->left;
delete rightMost;
}
size--;
return true;
}
#endif