#ifndef AVLTREE_H
#define AVLTREE_H
#include "BST.h"
#include <vector>
#include <algorithm>
#include <stdexcept>
using namespace std;
template<typename T>
class AVLTreeNode : public TreeNode<T>
{
public:
int height;
AVLTreeNode(T element) : TreeNode<T>(element)
{
height = 0;
}
};
template <typename T>
class AVLTree : public BST<T>
{
public:
AVLTree();
AVLTree(T elements[], int arraySize);
bool insert(T element);
bool remove(T element);
AVLTreeNode<T>* createNewNode(T element);
void balancePath(T element);
void updateHeight(AVLTreeNode<T>* node);
int balanceFactor(AVLTreeNode<T>* node);
void balanceLL(TreeNode<T>* A, TreeNode<T>* parentOfA);
void balanceLR(TreeNode<T>* A, TreeNode<T>* parentOfA);
void balanceRR(TreeNode<T>* A, TreeNode<T>* parentOfA);
void balanceRL(TreeNode<T>* A, TreeNode<T>* parentOfA);
private:
int height;
};
template <typename T>
AVLTree<T>::AVLTree()
{
height = 0;
}
template <typename T>
AVLTree<T>::AVLTree(T elements[], int arraySize)
{
root = NULL;
size = 0;
for (int i = 0; i < arraySize; i++)
{
insert(elements[i]);
}
}
template <typename T>
AVLTreeNode<T>* AVLTree<T>::createNewNode(T element)
{
return new AVLTreeNode<T>(element);
}
template <typename T>
bool AVLTree<T>::insert(T element)
{
bool successful = BST<T>::insert(element);
if (!successful)
return false;
else
balancePath(element);
return true;
}
template <typename T>
void AVLTree<T>::balancePath(T element)
{
vector<TreeNode<T>*>* p = path(element);
for (int i = (*p).size() - 1; i >= 0; i--)
{
AVLTreeNode<T>* A = static_cast<AVLTreeNode<T>*>((*p)[i]);
updateHeight(A);
AVLTreeNode<T>* parentOfA = (A == root) ? NULL :
static_cast<AVLTreeNode<T>*>((*p)[i - 1]);
switch (balanceFactor(A))
{
case -2:
if (balanceFactor(
static_cast<AVLTreeNode<T>*>(((*A).left))) <= 0)
balanceLL(A, parentOfA);
else
balanceLR(A, parentOfA);
break;
case +2:
if (balanceFactor(
static_cast<AVLTreeNode<T>*>(((*A).right))) >= 0)
balanceRR(A, parentOfA);
else
balanceRL(A, parentOfA);
}
}
}
template <typename T>
void AVLTree<T>::updateHeight(AVLTreeNode<T>* node)
{
if (node->left == NULL && node->right == NULL)
node->height = 0;
else if (node->left == NULL)
node->height =
1 + (*static_cast<AVLTreeNode<T>*>((node->right))).height;
else if (node->right == NULL)
node->height =
1 + (*static_cast<AVLTreeNode<T>*>((node->left))).height;
else
node->height = 1 +
max((*static_cast<AVLTreeNode<T>*>((node->right))).height,
(*static_cast<AVLTreeNode<T>*>((node->left))).height);
}
template <typename T>
int AVLTree<T>::balanceFactor(AVLTreeNode<T>* node)
{
if (node->right == NULL)
return -node->height;
else if (node->left == NULL)
return +node->height;
else
return (*static_cast<AVLTreeNode<T>*>((node->right))).height -
(*static_cast<AVLTreeNode<T>*>((node->left))).height;
}
template <typename T>
void AVLTree<T>::balanceLL(TreeNode<T>* A, TreeNode<T>* parentOfA)
{
TreeNode<T>* B = (*A).left;
if (A == root)
root = B;
else
if (parentOfA->left == A)
parentOfA->left = B;
else
parentOfA->right = B;
A->left = B->right;
B->right = A;
updateHeight(static_cast<AVLTreeNode<T>*>(A));
updateHeight(static_cast<AVLTreeNode<T>*>(B));
}
template <typename T>
void AVLTree<T>::balanceLR(TreeNode<T>* A, TreeNode<T>* parentOfA)
{
TreeNode<T>* B = A->left;
TreeNode<T>* C = B->right;
if (A == root)
root = C;
else
if (parentOfA->left == A)
parentOfA->left = C;
else
parentOfA->right = C;
A->left = C->right;
B->right = C->left;
C->left = B;
C->right = A;
updateHeight(static_cast<AVLTreeNode<T>*>(A));
updateHeight(static_cast<AVLTreeNode<T>*>(B));
updateHeight(static_cast<AVLTreeNode<T>*>(C));
}
template <typename T>
void AVLTree<T>::balanceRR(TreeNode<T>* A, TreeNode<T>* parentOfA)
{
TreeNode<T>* B = A->right;
if (A == root)
root = B;
else
if (parentOfA->left == A)
parentOfA->left = B;
else
parentOfA->right = B;
A->right = B->left;
B->left = A;
updateHeight(static_cast<AVLTreeNode<T>*>(A));
updateHeight(static_cast<AVLTreeNode<T>*>(B));
}
template <typename T>
void AVLTree<T>::balanceRL(TreeNode<T>* A, TreeNode<T>* parentOfA)
{
TreeNode<T>* B = A->right;
TreeNode<T>* C = B->left;
if (A == root)
root = C;
else
if (parentOfA->left == A)
parentOfA->left = C;
else
parentOfA->right = C;
A->right = C->left;
B->left = C->right;
C->left = A;
C->right = B;
updateHeight(static_cast<AVLTreeNode<T>*>(A));
updateHeight(static_cast<AVLTreeNode<T>*>(B));
updateHeight(static_cast<AVLTreeNode<T>*>(C));
}
template <typename T>
bool AVLTree<T>::remove(T element)
{
if (root == NULL)
return false;
TreeNode<T>* parent = NULL;
TreeNode<T>* current = root;
while (current != NULL)
{
if (element < current->element)
{
parent = current;
current = current->left;
}
else if (element > current->element)
{
parent = current;
current = current->right;
}
else
break;
}
if (current == NULL)
return false;
if (current->left == NULL)
{
if (parent == NULL)
root = current->right;
else
{
if (element < parent->element)
parent->left = current->right;
else
parent->right = current->right;
balancePath(parent->element);
}
}
else
{
TreeNode<T>* parentOfRightMost = current;
TreeNode<T>* rightMost = current->left;
while (rightMost->right != NULL)
{
parentOfRightMost = rightMost;
rightMost = rightMost->right;
}
current->element = rightMost->element;
if (parentOfRightMost->right == rightMost)
parentOfRightMost->right = rightMost->left;
else
parentOfRightMost->left = rightMost->left;
balancePath(parentOfRightMost->element);
}
size--;
return true;
}
#endif