#ifndef BINARY_SEARCH_TREE_H
#define BINARY_SEARCH_TREE_H
#include <iostream>
#include <algorithm>
#include "dsexceptions.h"
using namespace std;
template <typename Comparable>
class BinarySearchTree
{
public:
BinarySearchTree() : root{
nullptr } {
}
BinarySearchTree(const BinarySearchTree & rhs) : root{
nullptr }
{
root = clone(rhs.root);
}
BinarySearchTree(BinarySearchTree && rhs) : root{
rhs.root }
{
rhs.root = nullptr;
}
~BinarySearchTree()
{
makeEmpty();
}
const Comparable & findMin() const
{
if (isEmpty())
throw UnderflowException{
};
return findMin(root)->element;
}
const Comparable & findMax() const
{
if (isEmpty())
throw UnderflowException{
};
return findMax(root)->element;
}
bool contains(const Comparable & x) const
{
return contains(x, root);
}
bool isEmpty() const
{
return root == nullptr;
}
void printTree(ostream & out = cout) const
{
if (isEmpty()) {
out << "Empty Tree" << endl;
}
printTree(root, out);
}
void makeEmpty()
{
makeEmpty(root);
}
void insert(const Comparable & x)
{
insert(x, root);
}
void insert(Comparable && x)
{
insert(std::move(x), root);
}
void remove(const Comparable & x)
{
remove(x, root);
}
BinarySearchTree & operator=(const BinarySearchTree & rhs)
{
BinarySearchTree copy(rhs);
std::swap(*this, copy);
return *this;
}
BinarySearchTree & operator=(BinarySearchTree && rhs)
{
std::swap(root, rhs.root);
return *this;
}
private:
struct BinaryNode
{
Comparable element;
BinaryNode *left;
BinaryNode *right;
BinaryNode(const Comparable & theElement, BinaryNode *lt, BinaryNode *rt)
: element{
theElement }, left{
lt }, right{
rt } {
}
BinaryNode(Comparable && theElement, BinaryNode *lt, BinaryNode *rt)
: element{
std::move(theElement) }, left{
lt }, right{
rt } {
}
};
BinaryNode *root;
void insert(const Comparable & x, BinaryNode * & t)
{
if (t == nullptr)
t = new BinaryNode{
x, nullptr, nullptr };
else if (x < t->element)
insert(x, t->left);
else if (t->element < x)
insert(x, t->right);
else
;
}
void insert(Comparable && x, BinaryNode * & t)
{
if (t == nullptr)
t = new BinaryNode{
std::move(x), nullptr, nullptr };
else if (x < t->element)
insert(std::move(x), t->left);
else if (t->element < x)
insert(std::move(x), t->right);
else
;
}
void remove(const Comparable & x, BinaryNode * & t)
{
if (t == nullptr)
return;
if (x < t->element)
remove(x, t->left);
else if (t->element < x)
remove(x, t->right);
else if (t->left != nullptr && t->right != nullptr) {
t->element = findMin(t->right)->element;
remove(t->element, t->right);
}
else {
BinaryNode *oldNode = t;
t = (t->left != nullptr) ? t->left : t->right;
delete oldNode;
}
}
BinaryNode * findMin(BinaryNode *t) const
{
if (t == nullptr)
return nullptr;
if (t->left == nullptr)
return t;
return findMin(t->left);
}
BinaryNode * findMax(BinaryNode *t) const
{
if (t != nullptr)
while (t->right != nullptr)
t = t->right;
return t;
}
bool contains(const Comparable & x, BinaryNode *t) const
{
if (t == nullptr)
return false;
else if (x < t->element)
return contains(x, t->left);
else if (t->element < x)
return contains(x, t->right);
else
return true;
}
void makeEmpty(BinaryNode * & t)
{
if (t != nullptr) {
makeEmpty(t->left);
makeEmpty(t->right);
delete t;
}
t = nullptr;
}
void printTree(BinaryNode *t, ostream & out = cout) const
{
if (t == nullptr)
return;
printTree(t->left);
out << t->element << endl;
printTree(t->right);
}
BinaryNode *clone(BinaryNode *t) const
{
if (t == nullptr)
return nullptr;
else
return new BinaryNode{
t->element, clone(t->left), clone(t->right) };
}
};
#endif
#include "binary_search_tree.h"
#include <iostream>
using namespace std;
int main()
{
BinarySearchTree<int> t;
cout << "Add elements..." << endl;
for (int i = 0; i < 100; i += 2)
t.insert(i);
t.printTree();
cout << "Remove elements..." << endl;
for (int i = 0; i < 50; i++)
t.remove(i);
t.printTree();
cout << "Find max and min..." << endl;
int maxn = t.findMax();
int minn = t.findMin();
cout << "max is:" << maxn << " min is:" << minn << endl;
cout << "Contains..." << endl;
if (t.contains(1024))
cout << "Yes" << endl;
else
cout << "No" << endl;
cout << "Make empty..." << endl;
t.makeEmpty();
cout << "End of test..." << endl;
return 0;
}