Files
2019-01-11 20:27:28 +07:00

274 lines
5.6 KiB
C++

//use "balance" varialbe as "height"
#include "TreeSet.h"
static bool isSuccess;
TreeSet::TreeSet()
{
root = nullptr;
count = 0;
}
TreeSet::~TreeSet()
{
clear();
}
void TreeSet::clearRec(AVLNode *root)
{
if (root != nullptr) {
clearRec(root->left);
clearRec(root->right);
delete root;
}
}
void TreeSet::clear()
{
clearRec(root);
root = nullptr;
count = 0;
}
int TreeSet::add(int val)
{
isSuccess = false;
root = recursiveAdd(root, val);
if (isSuccess) {
++count;
return true;
}
return false;
}
bool TreeSet::contains(int val)
{
AVLNode *temp = root;
while (temp != nullptr) {
if (temp->key > val)
temp = temp->left;
else if (temp->key < val)
temp = temp->right;
else
return true;
}
return false;
}
void TreeSet::copy(const TreeSet &set)
{
clear();
root = recursiveCopy(set.root);
count = set.count;
}
int TreeSet::first()
{
if (root == nullptr) {
throw "NoSuchElementException";
}
AVLNode *temp = root;
while (temp->left != nullptr)
temp = temp->left;
return temp->key;
}
int TreeSet::last()
{
if (root == nullptr) {
throw "NoSuchElementException";
}
AVLNode *temp = root;
while (temp->right != nullptr)
temp = temp->right;
return temp->key;
}
int TreeSet::higher(int val)
{
if (root == nullptr)
return -1;
int higher = last();
if (val >= higher)
return -1;
AVLNode *temp = root;
while (temp != nullptr) {
if (temp->key > val) {
if (temp->key < higher)
higher = temp->key;
temp = temp->left;
} else {
temp = temp->right;
}
}
return higher;
}
int TreeSet::lower(int val)
{
if (root == nullptr)
return -1;
int lower = first();
if (val <= lower)
return -1;
AVLNode *temp = root;
while (temp != nullptr) {
if (temp->key < val) {
if (temp->key > lower)
lower = temp->key;
temp = temp->right;
} else {
temp = temp->left;
}
}
return lower;
}
int TreeSet::remove(int val)
{
isSuccess = false;
root = recursiveRemove(root, val);
if (isSuccess) {
--count;
return true;
}
return false;
}
TreeSet *TreeSet::subSet(int fromVal, int toVal)
{
TreeSet *subSet = new TreeSet;
recursiveSubSet(subSet, root, fromVal, toVal);
return subSet;
}
int TreeSet::size()
{
return count;
}
int TreeSet::getHeight(AVLNode *node)
{
if (node == nullptr)
return 0;
return node->balance;
}
void TreeSet::setHeight(AVLNode *&node)
{
node->balance = max(getHeight(node->left), getHeight(node->right)) + 1;
}
int TreeSet::getBalance(AVLNode *node)
{
if (node == nullptr)
return 0;
return getHeight(node->left) - getHeight(node->right);
}
void TreeSet::recursiveSubSet(TreeSet *&subSet, AVLNode *node, int fromVal, int toVal)
{
if (node == nullptr)
return;
if (node->key < fromVal) {
recursiveSubSet(subSet, node->right, fromVal, toVal);
} else if (node->key < toVal) {
subSet->add(node->key);
recursiveSubSet(subSet, node->left, fromVal, toVal);
recursiveSubSet(subSet, node->right, fromVal, toVal);
} else {
recursiveSubSet(subSet, node->left, fromVal, toVal);
}
}
AVLNode *TreeSet::recursiveAdd(AVLNode *&node, int val)
{
if (node == nullptr) {
isSuccess = true;
return new AVLNode(val, 1);
}
if (node->key == val)
return node;
if (node->key > val)
node->left = recursiveAdd(node->left, val);
else
node->right = recursiveAdd(node->right, val);
setHeight(node);
return rebalance(node);
}
AVLNode *TreeSet::recursiveRemove(AVLNode *&node, int val)
{
if (node == nullptr)
return node;
if (node->key > val) {
node->left = recursiveRemove(node->left, val);
} else if (node->key < val) {
node->right = recursiveRemove(node->right, val);
} else {
if (node->left == nullptr) {
AVLNode *temp = node->right;
delete node;
isSuccess = true;
return temp;
}
AVLNode *delNode = node->left;
while (delNode->right != nullptr)
delNode = delNode->right;
node->key = delNode->key;
node->left = recursiveRemove(node->left, node->key);
}
return rebalance(node);
}
AVLNode *TreeSet::recursiveCopy(AVLNode *node)
{
if (node == nullptr)
return node;
AVLNode *temp = new AVLNode(node->key, node->balance);
temp->left = recursiveCopy(node->left);
temp->right = recursiveCopy(node->right);
return temp;
}
AVLNode *TreeSet::rotateLeft(AVLNode *&node)
{
AVLNode *temp = node->right;
AVLNode *tmp = temp->left;
node->right = tmp;
temp->left = node;
setHeight(node);
setHeight(temp);
return temp;
}
AVLNode *TreeSet::rotateRight(AVLNode *&node)
{
AVLNode *temp = node->left;
AVLNode *tmp = temp->right;
node->left = tmp;
temp->right = node;
setHeight(node);
setHeight(temp);
return temp;
}
AVLNode *TreeSet::rebalance(AVLNode *&node)
{
if (node == nullptr)
return nullptr;
int balance = getBalance(node);
if (balance > 1) {
if (getBalance(node->left) < -1)
node->left = rotateLeft(node->left);
node = rotateRight(node);
} else if (balance < -1) {
if (getBalance(node->right) > 1)
node->right = rotateRight(node->right);
node = rotateLeft(node);
}
return node;
}